From: jenkins-bot Date: Thu, 7 Jan 2016 01:06:02 +0000 (+0000) Subject: Merge "Allow patrol of uploads" X-Git-Tag: 1.31.0-rc.0~8417 X-Git-Url: http://git.cyclocoop.org//%22http:/%22.attribut_html%28%24lesurls%5B%24numero%5D%29.%22/%22?a=commitdiff_plain;h=6505e5f278aae664f78fb8f876c10902d2195231;hp=c53f647658ade8652900994a4a78468d62ec616a;p=lhc%2Fweb%2Fwiklou.git Merge "Allow patrol of uploads" --- diff --git a/HISTORY b/HISTORY index 0410bd5672..e57d346316 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,14 @@ Change notes from older releases. For current info see RELEASE-NOTES-1.27. -== MediaWiki 1.26 == += MediaWiki 1.26 = + +== MediaWiki 1.26.2 == + +This is a maintenance release of the MediaWiki 1.26 branch. + +=== Changes since 1.26.1 === +* (T121892) Fix fatal error on some Special pages, introduced in 1.26.1. + == MediaWiki 1.26.1 == This is a maintenance release of the MediaWiki 1.26 branch. @@ -26,6 +34,8 @@ This is a maintenance release of the MediaWiki 1.26 branch. * Fix issue that breaks HHVM Repo Authorative mode. * (T120267) Work around APCu memory corruption bug +== MediaWiki 1.26.0 == + === Configuration changes in 1.26 === * $wgPasswordResetRoutes['email'] = true by default. * $wgEnableParserCache was deprecated, set $wgParserCacheType to CACHE_NONE @@ -115,7 +125,7 @@ This is a maintenance release of the MediaWiki 1.26 branch. documentation for mw.Upload.Dialog, mw.Upload.BookletLayout and its subclasses for more information. -== extension.json changes in 1.26 == +=== extension.json changes in 1.26 === * (T99344) The extension.json schema is now versioned. All extensions and skins should set a "manifest_version" property corresponding to the schema version they were written for. The only supported version @@ -268,7 +278,14 @@ changes to languages because of Phabricator reports. * $wgDeferredUpdateList was removed. * DeferredUpdates::addHTMLCacheUpdate() was removed. -== MediaWiki 1.25 == += MediaWiki 1.25 = + +== MediaWiki 1.25.5 == + +This is a maintenance release of the MediaWiki 1.25 branch. + +=== Changes since 1.25.4 === +* (T121892) Fix fatal error on some Special pages, introduced in 1.25.4. == MediaWiki 1.25.4 == @@ -348,6 +365,8 @@ This is a bug fix release of the MediaWiki 1.25 branch. === Changes since 1.25 === * (T100351) Fix syntax errors in extension.json of ConfirmEdit extension +== MediaWiki 1.25.0 == + === Configuration changes in 1.25 === * $wgPageShowWatchingUsers was removed. * $wgLocalVirtualHosts has been added to replace $wgConf->localVHosts. @@ -850,55 +869,20 @@ changes to languages because of Bugzilla reports. loadedScripts object, from wikibits.js (deprecated since 1.17) now emit warnings through mw.log.warn when accessed. += MediaWiki 1.24 = -== Compatibility == - -MediaWiki 1.25 requires PHP 5.3.3 or later. There is experimental support for -HHVM 3.3.0. - -MySQL is the recommended DBMS. PostgreSQL or SQLite can also be used, but -support for them is somewhat less mature. There is experimental support for -Oracle and Microsoft SQL Server. +== MediaWiki 1.24.6 == -The supported versions are: +This is a maintenance release of the MediaWiki 1.24 branch. -* MySQL 5.0.3 or later -* PostgreSQL 8.3 or later -* SQLite 3.3.7 or later -* Oracle 9.0.1 or later -* Microsoft SQL Server 2005 (9.00.1399) - -== Upgrading == - -1.25 has several database changes since 1.24, and will not work without schema -updates. Note that due to changes to some very large tables like the revision -table, the schema update may take quite long (minutes on a medium sized site, -many hours on a large site). - -If upgrading from before 1.11, and you are using a wiki as a commons -repository, make sure that it is updated as well. Otherwise, errors may arise -due to database schema changes. - -If upgrading from before 1.7, you may want to run refreshLinks.php to ensure -new database fields are filled with data. - -If you are upgrading from MediaWiki 1.4.x or earlier, you should upgrade to -1.5 first. The upgrade script maintenance/upgrade1_5.php has been removed -with MediaWiki 1.21. - -Don't forget to always back up your database before upgrading! - -See the file UPGRADE for more detailed upgrade instructions. - -For notes on 1.24.x and older releases, see HISTORY. - -== MediaWiki 1.24 == +=== Changes since 1.24.5 === +* (T121892) Fix fatal error on some Special pages, introduced in 1.24.5. == MediaWiki 1.24.5 == This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.24.4 == +=== Changes since 1.24.4 === * (T117899) SECURITY: $wgArticlePath can no longer be set to relative paths that do not begin with a slash. This enabled trivial XSS attacks. Configuration values such as "http://my.wiki.com/wiki/$1" are fine, as are @@ -920,7 +904,7 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. This is a security and maintenance release of the MediaWiki 1.24 branch. -== Changes since 1.24.3 == +=== Changes since 1.24.3 === * (T91653) Minimal PSR-3 debug logger to support backports from 1.25+. * (T68650) Fix indexing of moved pages with PostgreSQL. Requires running @@ -935,7 +919,7 @@ This is a security and maintenance release of the MediaWiki 1.24 branch. This is a security and maintenance release of the MediaWiki 1.24 branch. -== Changes since 1.24.2 == +=== Changes since 1.24.2 === * (T94116) SECURITY: Compare API watchlist token in constant time * (T97391) SECURITY: Escape error message strings in thumb.php @@ -949,7 +933,7 @@ This is a security and maintenance release of the MediaWiki 1.24 branch. This is a security and maintenance release of the MediaWiki 1.24 branch. -== Changes since 1.24.1 == +=== Changes since 1.24.1 === * (T85848, T71210) SECURITY: Don't parse XMP blocks that contain XML entities, to prevent various DoS attacks. @@ -973,7 +957,7 @@ This is a security and maintenance release of the MediaWiki 1.24 branch. This is a security and maintenance release of the MediaWiki 1.24 branch. -== Changes since 1.24.0 == +=== Changes since 1.24.0 === * (bug T76686) [SECURITY] thumb.php outputs wikitext message as raw HTML, which could lead to xss. Permission to edit MediaWiki namespace is required to @@ -986,6 +970,8 @@ This is a security and maintenance release of the MediaWiki 1.24 branch. * (bug T76168) OutputPage: Add accessors for some protected properties. * (bug T74834) Make 1.24 branch directly installable under PostgreSQL. +== MediaWiki 1.24.0 == + === Configuration changes in 1.24 === * MediaWiki will no longer run if register_globals is enabled. It has been deprecated for 5 years now, and was removed in PHP 5.4. For more information @@ -1678,14 +1664,20 @@ of files that are no longer available follows. * skins/common/images/icons/fileicon.png * skins/common/images/ksh/button_S_italic.png += MediaWiki 1.23 = + +== MediaWiki 1.23.13 == -== MediaWiki 1.23 == +This is a maintenance release of the MediaWiki 1.23 branch. + +=== Changes since 1.23.12 === +* (T121892) Fix fatal errors on some Special pages, introduced in 1.23.12. == MediaWiki 1.23.12 == This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.23.11 == +=== Changes since 1.23.11 === * (T117899) SECURITY: $wgArticlePath can no longer be set to relative paths that do not begin with a slash. This enabled trivial XSS attacks. Configuration values such as "http://my.wiki.com/wiki/$1" are fine, as are @@ -1706,7 +1698,7 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.23.10 == +=== Changes since 1.23.10 === * (T91850) SECURITY: Add throttle check in ApiUpload and SpecialUpload * (T91203, T91205) SECURITY: API: Improve validation in chunked uploading @@ -1716,7 +1708,7 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.23.9 == +=== Changes since 1.23.9 === * (T94116) SECURITY: Compare API watchlist token in constant time * (T97391) SECURITY: Escape error message strings in thumb.php @@ -1731,7 +1723,7 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.23.8 == +=== Changes since 1.23.8 === * (T85848, T71210) SECURITY: Don't parse XMP blocks that contain XML entities, to prevent various DoS attacks. @@ -1744,14 +1736,14 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. prevent XSS and protect viewer's privacy. * (bug T68650) Fix indexing of moved pages with PostgreSQL. Requires running update.php to fix. -* (bug T70087) Fix Special:ActiveUsers page for installations using +* (bug T70087) Fix Special:ActiveUsers page for installations using PostgreSQL. == MediaWiki 1.23.8 == This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.23.7 == +=== Changes since 1.23.7 === * (bug T76686) [SECURITY] thumb.php outputs wikitext message as raw HTML, which could lead to xss. Permission to edit MediaWiki namespace is required to @@ -1765,7 +1757,7 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. This is a security and maintenance release of the MediaWiki 1.23 branch. -== Changes since 1.23.6 == +=== Changes since 1.23.6 === * (bugs 66776, 71478) SECURITY: User PleaseStand reported a way to inject code into API clients that used format=php to process pages that underwent flash @@ -1869,6 +1861,7 @@ This is a security and maintenance release of the MediaWiki 1.23 branch. like only extracting the tail of the file partially or not at all. * (bug 66182) Removed -x flag on some php files. +== MediaWiki 1.23.0 == === Configuration changes in 1.23 === * (bug 13250) Restored method for clearing a watchlist in web UI @@ -2337,7 +2330,7 @@ changes to languages because of Bugzilla reports. ==== Removed globals ==== * $wgBetterDirectionality (deprecated in 1.18) -== MediaWiki 1.22 == += MediaWiki 1.22 = == MediaWiki 1.22.15 == @@ -2493,6 +2486,8 @@ This is a security and maintenance release of the MediaWiki 1.22 branch. * (bug 47055) Changed FOR UPDATE handling in Postgresql * (bug 57026) Avoid extra parsing in prepareContentForEdit() +== MediaWiki 1.22.0 == + === Configuration changes in 1.22 === * $wgRedirectScript was removed. It was unused. * Removed $wgLocalMessageCacheSerialized, it is now always true. @@ -2902,7 +2897,7 @@ This is a security and maintenance release of the MediaWiki 1.22 branch. file repositories, and related ForeignAPIRepo methods getInfo and getApiUrl. * The new query module list=allfileusages to enumerate file usages was added. -=== Languages updated in 1.22=== +=== Languages updated in 1.22 === MediaWiki supports over 350 languages. Many localisations are updated regularly. Below only new and removed languages are listed, as well as @@ -3020,7 +3015,7 @@ changes to languages because of Bugzilla reports. * mediawiki.util: mw.util.wikiGetlink has been renamed to getUrl. (The old name still works, but is deprecated.) -== MediaWiki 1.21 == += MediaWiki 1.21 = == MediaWiki 1.21.11 == This is a security and maintenance release of the MediaWiki 1.21 branch. @@ -3108,6 +3103,8 @@ This is a maintenance release of the MediaWiki 1.21 branch. * A problem with the Oracle SQL table creation was fixed. * (PdfHandler extension) Fix warning if pdfinfo fails but pdftext succeeds. +== MediaWiki 1.21.0 == + === Configuration changes in 1.21 === * (bug 29374) $wgVectorUseSimpleSearch is now enabled by default. * Deprecated $wgAllowRealName is removed. Use $wgHiddenPrefs[] = 'realname' @@ -3436,7 +3433,7 @@ changes to languages because of Bugzilla reports. * BREAKING CHANGE: (bug 38244) Removed the mediawiki.api.titleblacklist module and moved it to the TitleBlacklist extension. -== MediaWiki 1.20 == += MediaWiki 1.20 = == MediaWiki 1.20.8 == This is a security release of the MediaWiki 1.20 branch. @@ -3489,7 +3486,7 @@ This is a security release of the MediaWiki 1.20 branch. == MediaWiki 1.20.3 == This is a security and maintenance release of the MediaWiki 1.20 branch. -== MediaWiki 1.20.2 == +=== Changes since MediaWiki 1.20.2 === * New preference type - 'api'. Preferences of this type are not shown on Special:Preferences, but are still available via the action=options API. (Unbreaks MLEB.) * (bug 44010) Context is passed to UserGetLanguageObject. * The recursion guard on RequestContext::getLanguage() was weakened. @@ -3503,14 +3500,14 @@ This is a security and maintenance release of the MediaWiki 1.20 branch. == MediaWiki 1.20.2 == This is a maintenance release of the MediaWiki 1.20 branch -== MediaWiki 1.20.1 == +=== Changes since MediaWiki 1.20.1 === * (bug 42638) Fix API action=options&reset=1 & unit tests. * (bug 42370) Fixed backport of 60cc060 to use mDoneWrites — caused * (bug 42592) User rights, preferences and other things are not saving in 1.20.1. == MediaWiki 1.20.1 == This is a security release of the MediaWiki 1.20 branch -Changes since 1.20 +=== Changes since 1.20.0 === * (bug 42202) Validate options to prevent html injection * (bug 40995) Prevent session fixation in Special:UserLogin (CVE-2012-5391) * (bug 41400) Prevent linker regex from exceeding PCRE backtrack limit @@ -3518,9 +3515,7 @@ Changes since 1.20 * (bug 40632) Remove CleanupPresentationalAttributes feature * [Database] Fixed case where trx idle callbacks might be lost. - - -== MediaWiki 1.20 == +== MediaWiki 1.20.0 == === PHP 5.3 now required === Since 1.20, the lowest supported version of PHP is now 5.3.2. Please @@ -3887,7 +3882,7 @@ changes to languages because of Bugzilla reports. == MediaWiki 1.19.21 == This is a maintenance release of the MediaWiki 1.19 branch. -=== Changes since 1.19.20=== +=== Changes since 1.19.20 === * (bug 67440) Allow classes to be registered properly from installer. * (bug 47281) Fixed a dumpBackup.php error with --uploads --include-filesoptions: Unable to find the wrapper "mwstore". * System administrators are encouraged to upgrade to this release or 1.22+ and produce a full data dump. https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Backing_up_a_wiki * (bug 63049) Removed anonymous functions from ApiFormatBase, added in1.19.13 as part of the fix for bug 61362, for PHP 5.2 compatibility. @@ -3895,73 +3890,73 @@ This is a maintenance release of the MediaWiki 1.19 branch. == MediaWiki 1.19.20 == This is a security release of the MediaWiki 1.19 branch. -=== Changes since 1.19.19=== +=== Changes since 1.19.19 === * (bug 70672) SECURITY: OutputPage: Remove separation of css and js module allowance. == MediaWiki 1.19.19 == This is a security release of the MediaWiki 1.19 branch. -=== Changes since 1.19.18=== +=== Changes since 1.19.18 === * (bug 69008) SECURITY: Enhance CSS filtering in SVG files. Filter - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option2/noderiv.svg b/resources/src/mediawiki/bookletlayout/option2/noderiv.svg index c3ee55be2c..96d80845ed 100644 --- a/resources/src/mediawiki/bookletlayout/option2/noderiv.svg +++ b/resources/src/mediawiki/bookletlayout/option2/noderiv.svg @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option2/ownwork.svg b/resources/src/mediawiki/bookletlayout/option2/ownwork.svg index 639775f939..dc660c83ff 100644 --- a/resources/src/mediawiki/bookletlayout/option2/ownwork.svg +++ b/resources/src/mediawiki/bookletlayout/option2/ownwork.svg @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option2/useful.svg b/resources/src/mediawiki/bookletlayout/option2/useful.svg index baa982bf6c..2af3f938fa 100644 --- a/resources/src/mediawiki/bookletlayout/option2/useful.svg +++ b/resources/src/mediawiki/bookletlayout/option2/useful.svg @@ -1,24 +1,24 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option4/camera.svg b/resources/src/mediawiki/bookletlayout/option4/camera.svg index dc43b5defa..b1103968eb 100644 --- a/resources/src/mediawiki/bookletlayout/option4/camera.svg +++ b/resources/src/mediawiki/bookletlayout/option4/camera.svg @@ -1,60 +1,60 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option4/graphics.svg b/resources/src/mediawiki/bookletlayout/option4/graphics.svg index ff3d6821b2..c32f79fb17 100644 --- a/resources/src/mediawiki/bookletlayout/option4/graphics.svg +++ b/resources/src/mediawiki/bookletlayout/option4/graphics.svg @@ -1,98 +1,98 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option4/search-ltr.svg b/resources/src/mediawiki/bookletlayout/option4/search-ltr.svg index 7bcf826362..67c4ef0890 100644 --- a/resources/src/mediawiki/bookletlayout/option4/search-ltr.svg +++ b/resources/src/mediawiki/bookletlayout/option4/search-ltr.svg @@ -1,92 +1,92 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option4/search-rtl.svg b/resources/src/mediawiki/bookletlayout/option4/search-rtl.svg index 408f9e694e..17c54d2f63 100644 --- a/resources/src/mediawiki/bookletlayout/option4/search-rtl.svg +++ b/resources/src/mediawiki/bookletlayout/option4/search-rtl.svg @@ -1,53 +1,53 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option4/website-ltr.svg b/resources/src/mediawiki/bookletlayout/option4/website-ltr.svg index c6bf6fef18..ed07c6135c 100644 --- a/resources/src/mediawiki/bookletlayout/option4/website-ltr.svg +++ b/resources/src/mediawiki/bookletlayout/option4/website-ltr.svg @@ -1,57 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/bookletlayout/option4/website-rtl.svg b/resources/src/mediawiki/bookletlayout/option4/website-rtl.svg index 080045ab10..dd8b0f0719 100644 --- a/resources/src/mediawiki/bookletlayout/option4/website-rtl.svg +++ b/resources/src/mediawiki/bookletlayout/option4/website-rtl.svg @@ -1,69 +1,69 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js b/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js index 7ba73bf2f8..48060973bc 100644 --- a/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js +++ b/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js @@ -43,7 +43,7 @@ mw.ForeignStructuredUpload.BookletLayout.parent.prototype.initialize.call( this ) .done( function () { // Point the CategorySelector to the right wiki - this.upload.apiPromise.done( function ( api ) { + this.upload.getApi().done( function ( api ) { // If this is a ForeignApi, it will have a apiUrl, otherwise we don't need to do anything if ( api.apiUrl ) { // Can't reuse the same object, CategorySelector calls #abort on its mw.Api instance @@ -183,6 +183,20 @@ this.selectFileWidget.on( 'change', onUploadFormChange.bind( this ) ); this.ownWorkCheckbox.on( 'change', onUploadFormChange.bind( this ) ); + this.selectFileWidget.on( 'change', function () { + var file = layout.getFile(); + + // Set the date to lastModified once we have the file + if ( layout.getDateFromLastModified( file ) !== undefined ) { + layout.dateWidget.setValue( layout.getDateFromLastModified( file ) ); + } + + // Check if we have EXIF data and set to that where available + layout.getDateFromExif( file ).done( function ( date ) { + layout.dateWidget.setValue( date ); + } ); + } ); + return this.uploadForm; }; @@ -463,20 +477,20 @@ } ); this.descriptionWidget = new OO.ui.TextInputWidget( { required: true, - validate: /.+/, + validate: /\S+/, multiline: true, autosize: true } ); - this.dateWidget = new mw.widgets.DateInputWidget( { - $overlay: this.$overlay, - required: true, - mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow - } ); this.categoriesWidget = new mw.widgets.CategorySelector( { // Can't be done here because we don't know the target wiki yet... done in #initialize. // api: new mw.ForeignApi( ... ), $overlay: this.$overlay } ); + this.dateWidget = new mw.widgets.DateInputWidget( { + $overlay: this.$overlay, + required: true, + mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow + } ); fieldset = new OO.ui.FieldsetLayout( { label: mw.msg( 'upload-form-label-infoform-title' ) @@ -484,11 +498,13 @@ fieldset.addItems( [ new OO.ui.FieldLayout( this.filenameWidget, { label: mw.msg( 'upload-form-label-infoform-name' ), - align: 'top' + align: 'top', + help: mw.msg( 'upload-form-label-infoform-name-tooltip' ) } ), new OO.ui.FieldLayout( this.descriptionWidget, { label: mw.msg( 'upload-form-label-infoform-description' ), - align: 'top' + align: 'top', + help: mw.msg( 'upload-form-label-infoform-description-tooltip' ) } ), new OO.ui.FieldLayout( this.categoriesWidget, { label: mw.msg( 'foreign-structured-upload-form-label-infoform-categories' ), @@ -540,6 +556,71 @@ return this.upload.getText(); }; + /** + * Get original date from EXIF data + * + * @param {Object} file + * @return {jQuery.Promise} Promise resolved with the EXIF date + */ + mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromExif = function ( file ) { + var fileReader, + deferred = $.Deferred(); + + if ( file && file.type === 'image/jpeg' ) { + fileReader = new FileReader(); + fileReader.onload = function () { + var fileStr, arr, i, metadata; + + if ( typeof fileReader.result === 'string' ) { + fileStr = fileReader.result; + } else { + // Array buffer; convert to binary string for the library. + arr = new Uint8Array( fileReader.result ); + fileStr = ''; + for ( i = 0; i < arr.byteLength; i++ ) { + fileStr += String.fromCharCode( arr[ i ] ); + } + } + + try { + metadata = mw.libs.jpegmeta( this.result, file.name ); + } catch ( e ) { + metadata = null; + } + + if ( metadata !== null && metadata.exif !== undefined && metadata.exif.DateTimeOriginal ) { + deferred.resolve( moment( metadata.exif.DateTimeOriginal, 'YYYY:MM:DD' ).format( 'YYYY-MM-DD' ) ); + } else { + deferred.reject(); + } + }; + + if ( 'readAsBinaryString' in fileReader ) { + fileReader.readAsBinaryString( file ); + } else if ( 'readAsArrayBuffer' in fileReader ) { + fileReader.readAsArrayBuffer( file ); + } else { + // We should never get here + deferred.reject(); + throw new Error( 'Cannot read thumbnail as binary string or array buffer.' ); + } + } + + return deferred.promise(); + }; + + /** + * Get last modified date from file + * + * @param {Object} file + * @return {Object} Last modified date from file + */ + mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromLastModified = function ( file ) { + if ( file && file.lastModified ) { + return moment( file.lastModified ).format( 'YYYY-MM-DD' ); + } + }; + /* Setters */ /** diff --git a/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js b/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js index 768efc3f81..c03c0d1939 100644 --- a/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js +++ b/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js @@ -197,9 +197,18 @@ * @return {string} */ ForeignStructuredUpload.prototype.getUser = function () { - var username = mw.config.get( 'wgUserName' ); - // Do not localise 'User:', we don't know the language of target wiki - return '[[User:' + username + '|' + username + ']]'; + var username, namespace; + // Do not localise, we don't know the language of target wiki + namespace = 'User'; + username = mw.config.get( 'wgUserName' ); + if ( !username ) { + // The user is not logged in locally. However, they might be logged in on the foreign wiki. + // We should record their username there. (If they're not logged in there either, this will + // record the IP address.) It's also possible that the user opened this dialog, got an error + // about not being logged in, logged in in another browser tab, then continued uploading. + username = '{{subst:REVISIONUSER}}'; + } + return '[[' + namespace + ':' + username + '|' + username + ']]'; }; mw.ForeignStructuredUpload = ForeignStructuredUpload; diff --git a/resources/src/mediawiki/mediawiki.ForeignUpload.js b/resources/src/mediawiki/mediawiki.ForeignUpload.js index 61fb59f609..aa08b6cd7c 100644 --- a/resources/src/mediawiki/mediawiki.ForeignUpload.js +++ b/resources/src/mediawiki/mediawiki.ForeignUpload.js @@ -109,6 +109,13 @@ * or to local uploads if no foreign target is configured. */ + /** + * @inheritdoc + */ + ForeignUpload.prototype.getApi = function () { + return this.apiPromise; + }; + /** * Override from mw.Upload to make sure the API info is found and allowed */ diff --git a/resources/src/mediawiki/mediawiki.Title.js b/resources/src/mediawiki/mediawiki.Title.js index 47250eea0a..033636cfea 100644 --- a/resources/src/mediawiki/mediawiki.Title.js +++ b/resources/src/mediawiki/mediawiki.Title.js @@ -906,7 +906,12 @@ * @return {string} */ getUrl: function ( params ) { - return mw.util.getUrl( this.toString(), params ); + var fragment = this.getFragment(); + if ( fragment ) { + return mw.util.getUrl( this.toString() + '#' + this.getFragment(), params ); + } else { + return mw.util.getUrl( this.toString(), params ); + } }, /** diff --git a/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js b/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js index e4197dc79f..1cd9101511 100644 --- a/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js +++ b/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js @@ -152,7 +152,6 @@ */ mw.Upload.BookletLayout.prototype.initialize = function () { var - apiPromise, booklet = this, deferred = $.Deferred(); @@ -160,8 +159,7 @@ this.upload = this.createUpload(); this.setPage( 'upload' ); - apiPromise = this.upload.apiPromise || $.Deferred().resolve( this.upload.api ); - apiPromise.done( function ( api ) { + this.upload.getApi().done( function ( api ) { // If the user can't upload anything, don't give them the option to. api.getUserInfo().done( function ( userInfo ) { if ( userInfo.rights.indexOf( 'upload' ) === -1 ) { @@ -202,7 +200,8 @@ layout = this, file = this.getFile(); - this.filenameWidget.setValue( file.name ); + this.setFilename( file.name ); + this.setPage( 'info' ); if ( this.shouldRecordBucket ) { @@ -210,8 +209,8 @@ } this.upload.setFile( file ); - // Explicitly set the filename so that the old filename isn't used in case of retry - this.upload.setFilenameFromFile(); + // The original file name might contain invalid characters, so use our sanitized one + this.upload.setFilename( this.getFilename() ); this.uploadPromise = this.upload.uploadToStash(); this.uploadPromise.then( function () { @@ -353,7 +352,7 @@ } else if ( warnings.badfilename !== undefined ) { // Change the name if the current name isn't acceptable // TODO This might not really be the best place to do this - this.filenameWidget.setValue( warnings.badfilename ); + this.setFilename( warnings.badfilename ); return new OO.ui.Error( $( '

' ).msg( 'badfilename', warnings.badfilename ) ); @@ -422,7 +421,7 @@ this.descriptionWidget = new OO.ui.TextInputWidget( { indicator: 'required', required: true, - validate: /.+/, + validate: /\S+/, multiline: true, autosize: true } ); @@ -433,11 +432,13 @@ fieldset.addItems( [ new OO.ui.FieldLayout( this.filenameWidget, { label: mw.msg( 'upload-form-label-infoform-name' ), - align: 'top' + align: 'top', + help: mw.msg( 'upload-form-label-infoform-name-tooltip' ) } ), new OO.ui.FieldLayout( this.descriptionWidget, { label: mw.msg( 'upload-form-label-infoform-description' ), - align: 'top' + align: 'top', + help: mw.msg( 'upload-form-label-infoform-description-tooltip' ) } ) ] ); this.infoForm = new OO.ui.FormLayout( { items: [ fieldset ] } ); @@ -512,7 +513,30 @@ * @return {string} */ mw.Upload.BookletLayout.prototype.getFilename = function () { - return this.filenameWidget.getValue(); + var filename = this.filenameWidget.getValue(); + if ( this.filenameExtension ) { + filename += '.' + this.filenameExtension; + } + return filename; + }; + + /** + * Prefills the {@link #infoForm information form} with the given filename. + * + * @protected + * @param {string} filename + */ + mw.Upload.BookletLayout.prototype.setFilename = function ( filename ) { + var title = mw.Title.newFromFileName( filename ); + + if ( title ) { + this.filenameWidget.setValue( title.getNameText() ); + this.filenameExtension = mw.Title.normalizeExtension( title.getExtension() ); + } else { + // Seems to happen for files with no extension, which should fail some checks anyway... + this.filenameWidget.setValue( filename ); + this.filenameExtension = null; + } }; /** diff --git a/resources/src/mediawiki/mediawiki.Upload.js b/resources/src/mediawiki/mediawiki.Upload.js index d80b4ebcc7..8a74ffc6ab 100644 --- a/resources/src/mediawiki/mediawiki.Upload.js +++ b/resources/src/mediawiki/mediawiki.Upload.js @@ -62,6 +62,17 @@ UP = Upload.prototype; + /** + * Get the mw.Api instance used by this Upload object. + * + * @return {jQuery.Promise} + * @return {Function} return.done + * @return {mw.Api} return.done.api + */ + UP.getApi = function () { + return $.Deferred().resolve( this.api ).promise(); + }; + /** * Set the text of the file page, to be created on file upload. * diff --git a/resources/src/mediawiki/mediawiki.inspect.js b/resources/src/mediawiki/mediawiki.inspect.js index 514a3dd15e..d4449231f8 100644 --- a/resources/src/mediawiki/mediawiki.inspect.js +++ b/resources/src/mediawiki/mediawiki.inspect.js @@ -20,7 +20,7 @@ function humanSize( bytes ) { if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; } var i = 0, - units = [ '', ' kB', ' MB', ' GB', ' TB', ' PB' ]; + units = [ '', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB' ]; for ( ; bytes >= 1024; bytes /= 1024 ) { i++; } // Maintain one decimal for kB and above, but don't diff --git a/resources/src/mediawiki/mediawiki.template.js b/resources/src/mediawiki/mediawiki.template.js index 91f1aff7ce..5e0e343250 100644 --- a/resources/src/mediawiki/mediawiki.template.js +++ b/resources/src/mediawiki/mediawiki.template.js @@ -8,43 +8,47 @@ mw.template = { /** - * Register a new compiler and template. + * Register a new compiler. * - * @param {string} name of compiler. Should also match with any file extensions of templates that want to use it. - * @param {Function} compiler which must implement a compile function + * A compiler is any object that implements a compile() method. The compile() method must + * return a Template interface with a method render() that returns HTML. + * + * The compiler name must correspond with the name suffix of templates that use this compiler. + * + * @param {string} name Compiler name + * @param {Object} compiler */ registerCompiler: function ( name, compiler ) { if ( !compiler.compile ) { - throw new Error( 'Compiler must implement compile method.' ); + throw new Error( 'Compiler must implement a compile method' ); } compilers[ name ] = compiler; }, /** - * Get the name of the compiler associated with a template based on its name. + * Get the name of the associated compiler based on a template name. * - * @param {string} templateName Name of template (including file suffix) - * @return {string} Name of compiler + * @param {string} templateName Name of a template (including suffix) + * @return {string} Name of a compiler */ getCompilerName: function ( templateName ) { - var templateParts = templateName.split( '.' ); - - if ( templateParts.length < 2 ) { - throw new Error( 'Unable to identify compiler. Template name must have a suffix.' ); + var nameParts = templateName.split( '.' ); + if ( nameParts.length < 2 ) { + throw new Error( 'Template name must have a suffix' ); } - return templateParts[ templateParts.length - 1 ]; + return nameParts[ nameParts.length - 1 ]; }, /** - * Get the compiler for a given compiler name. + * Get a compiler via its name. * - * @param {string} compilerName Name of the compiler - * @return {Object} The compiler associated with that name + * @param {string} name Name of a compiler + * @return {Object} The compiler */ - getCompiler: function ( compilerName ) { - var compiler = compilers[ compilerName ]; + getCompiler: function ( name ) { + var compiler = compilers[ name ]; if ( !compiler ) { - throw new Error( 'Unknown compiler ' + compilerName ); + throw new Error( 'Unknown compiler ' + name ); } return compiler; }, @@ -52,57 +56,54 @@ /** * Register a template associated with a module. * - * Compiles the newly added template based on the suffix in its name. + * Precompiles the newly added template based on the suffix in its name. * - * @param {string} moduleName Name of ResourceLoader module to get the template from - * @param {string} templateName Name of template to add including file extension - * @param {string} templateBody Contents of a template (e.g. html markup) - * @return {Function} Compiled template + * @param {string} moduleName Name of the ResourceLoader module the template is associated with + * @param {string} templateName Name of the template (including suffix) + * @param {string} templateBody Contents of the template (e.g. html markup) + * @return {Object} Compiled template */ add: function ( moduleName, templateName, templateBody ) { - var compiledTemplate, - compilerName = this.getCompilerName( templateName ); - + // Precompile and add to cache + var compiled = this.compile( templateBody, this.getCompilerName( templateName ) ); if ( !compiledTemplates[ moduleName ] ) { compiledTemplates[ moduleName ] = {}; } + compiledTemplates[ moduleName ][ templateName ] = compiled; - compiledTemplate = this.compile( templateBody, compilerName ); - compiledTemplates[ moduleName ][ templateName ] = compiledTemplate; - return compiledTemplate; + return compiled; }, /** - * Retrieve a template by module and template name. + * Get a compiled template by module and template name. * * @param {string} moduleName Name of the module to retrieve the template from * @param {string} templateName Name of template to be retrieved * @return {Object} Compiled template */ get: function ( moduleName, templateName ) { - var moduleTemplates, compiledTemplate; + var moduleTemplates; - // Check if the template has already been compiled, compile it if not - if ( !compiledTemplates[ moduleName ] || !compiledTemplates[ moduleName ][ templateName ] ) { - moduleTemplates = mw.templates.get( moduleName ); - if ( !moduleTemplates || !moduleTemplates[ templateName ] ) { - throw new Error( 'Template ' + templateName + ' not found in module ' + moduleName ); - } + // Try cache first + if ( compiledTemplates[ moduleName ] && compiledTemplates[ moduleName ][ templateName ] ) { + return compiledTemplates[ moduleName ][ templateName ]; + } - // Add compiled version - compiledTemplate = this.add( moduleName, templateName, moduleTemplates[ templateName ] ); - } else { - compiledTemplate = compiledTemplates[ moduleName ][ templateName ]; + moduleTemplates = mw.templates.get( moduleName ); + if ( !moduleTemplates || !moduleTemplates[ templateName ] ) { + throw new Error( 'Template ' + templateName + ' not found in module ' + moduleName ); } - return compiledTemplate; + + // Compiled and add to cache + return this.add( moduleName, templateName, moduleTemplates[ templateName ] ); }, /** - * Wrap our template engine of choice. + * Compile a string of template markup with an engine of choice. * * @param {string} templateBody Template body * @param {string} compilerName The name of a registered compiler - * @return {Object} Template interface + * @return {Object} Compiled template */ compile: function ( templateBody, compilerName ) { return this.getCompiler( compilerName ).compile( templateBody ); diff --git a/resources/src/mediawiki/mediawiki.template.mustache.js b/resources/src/mediawiki/mediawiki.template.mustache.js index 624986a9bb..7f62256adf 100644 --- a/resources/src/mediawiki/mediawiki.template.mustache.js +++ b/resources/src/mediawiki/mediawiki.template.mustache.js @@ -4,8 +4,27 @@ mw.template.registerCompiler( 'mustache', { compile: function ( src ) { return { - render: function ( data ) { - return $( $.parseHTML( Mustache.render( src, data ) ) ); + /** + * @ignore + * @return {string} The raw source code of the template + */ + getSource: function () { + return src; + }, + /** + * @ignore + * @param {Object} data Data to render + * @param {Object} partialTemplates Map partial names to Mustache template objects + * returned by mw.template.get() + */ + render: function ( data, partialTemplates ) { + var partials = {}; + if ( partialTemplates ) { + $.each( partialTemplates, function ( name, template ) { + partials[ name ] = template.getSource(); + } ); + } + return $( $.parseHTML( Mustache.render( src, data, partials ) ) ); } }; } diff --git a/resources/src/mediawiki/page/patrol.ajax.js b/resources/src/mediawiki/page/patrol.ajax.js new file mode 100644 index 0000000000..f9b0d3564b --- /dev/null +++ b/resources/src/mediawiki/page/patrol.ajax.js @@ -0,0 +1,65 @@ +/*! + * Animate patrol links to use asynchronous API requests to + * patrol pages, rather than navigating to a different URI. + * + * @since 1.21 + * @author Marius Hoch + */ +( function ( mw, $ ) { + if ( !mw.user.tokens.exists( 'patrolToken' ) ) { + // Current user has no patrol right, or an old cached version of user.tokens + // that didn't have patrolToken yet. + return; + } + $( function () { + var $patrolLinks = $( '.patrollink a' ); + $patrolLinks.on( 'click', function ( e ) { + var $spinner, href, rcid, apiRequest; + + // Start preloading the notification module (normally loaded by mw.notify()) + mw.loader.load( 'mediawiki.notification' ); + + // Hide the link and create a spinner to show it inside the brackets. + $spinner = $.createSpinner( { + size: 'small', + type: 'inline' + } ); + $( this ).hide().after( $spinner ); + + href = $( this ).attr( 'href' ); + rcid = mw.util.getParamValue( 'rcid', href ); + apiRequest = new mw.Api(); + + apiRequest.postWithToken( 'patrol', { + action: 'patrol', + rcid: rcid + } ) + .done( function ( data ) { + // Remove all patrollinks from the page (including any spinners inside). + $patrolLinks.closest( '.patrollink' ).remove(); + if ( data.patrol !== undefined ) { + // Success + var title = new mw.Title( data.patrol.title ); + mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) ); + } else { + // This should never happen as errors should trigger fail + mw.notify( mw.msg( 'markedaspatrollederrornotify' ), { type: 'error' } ); + } + } ) + .fail( function ( error ) { + $spinner.remove(); + // Restore the patrol link. This allows the user to try again + // (or open it in a new window, bypassing this ajax module). + $patrolLinks.show(); + if ( error === 'noautopatrol' ) { + // Can't patrol own + mw.notify( mw.msg( 'markedaspatrollederror-noautopatrol' ), { type: 'warn' } ); + } else { + mw.notify( mw.msg( 'markedaspatrollederrornotify' ), { type: 'error' } ); + } + } ); + + e.preventDefault(); + } ); + } ); +}( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki/page/patrol.js b/resources/src/mediawiki/page/patrol.js deleted file mode 100644 index f9b0d3564b..0000000000 --- a/resources/src/mediawiki/page/patrol.js +++ /dev/null @@ -1,65 +0,0 @@ -/*! - * Animate patrol links to use asynchronous API requests to - * patrol pages, rather than navigating to a different URI. - * - * @since 1.21 - * @author Marius Hoch - */ -( function ( mw, $ ) { - if ( !mw.user.tokens.exists( 'patrolToken' ) ) { - // Current user has no patrol right, or an old cached version of user.tokens - // that didn't have patrolToken yet. - return; - } - $( function () { - var $patrolLinks = $( '.patrollink a' ); - $patrolLinks.on( 'click', function ( e ) { - var $spinner, href, rcid, apiRequest; - - // Start preloading the notification module (normally loaded by mw.notify()) - mw.loader.load( 'mediawiki.notification' ); - - // Hide the link and create a spinner to show it inside the brackets. - $spinner = $.createSpinner( { - size: 'small', - type: 'inline' - } ); - $( this ).hide().after( $spinner ); - - href = $( this ).attr( 'href' ); - rcid = mw.util.getParamValue( 'rcid', href ); - apiRequest = new mw.Api(); - - apiRequest.postWithToken( 'patrol', { - action: 'patrol', - rcid: rcid - } ) - .done( function ( data ) { - // Remove all patrollinks from the page (including any spinners inside). - $patrolLinks.closest( '.patrollink' ).remove(); - if ( data.patrol !== undefined ) { - // Success - var title = new mw.Title( data.patrol.title ); - mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) ); - } else { - // This should never happen as errors should trigger fail - mw.notify( mw.msg( 'markedaspatrollederrornotify' ), { type: 'error' } ); - } - } ) - .fail( function ( error ) { - $spinner.remove(); - // Restore the patrol link. This allows the user to try again - // (or open it in a new window, bypassing this ajax module). - $patrolLinks.show(); - if ( error === 'noautopatrol' ) { - // Can't patrol own - mw.notify( mw.msg( 'markedaspatrollederror-noautopatrol' ), { type: 'warn' } ); - } else { - mw.notify( mw.msg( 'markedaspatrollederrornotify' ), { type: 'error' } ); - } - } ); - - e.preventDefault(); - } ); - } ); -}( mediaWiki, jQuery ) ); diff --git a/resources/src/mediawiki/page/ready.js b/resources/src/mediawiki/page/ready.js index 9505bdd1e0..4385a2e903 100644 --- a/resources/src/mediawiki/page/ready.js +++ b/resources/src/mediawiki/page/ready.js @@ -70,6 +70,25 @@ } ); } + $nodes = $( '.catlinks[data-mw="interface"]' ); + if ( $nodes.length ) { + /** + * Fired when categories are being added to the DOM + * + * It is encouraged to fire it before the main DOM is changed (when $content + * is still detached). However, this order is not defined either way, so you + * should only rely on $content itself. + * + * This includes the ready event on a page load (including post-edit loads) + * and when content has been previewed with LivePreview. + * + * @event wikipage_categories + * @member mw.hook + * @param {jQuery} $content The most appropriate element containing the content, + * such as .catlinks + */ + mw.hook( 'wikipage.categories' ).fire( $nodes ); + } } ); }( mediaWiki, jQuery ) ); diff --git a/resources/src/startup.js b/resources/src/startup.js index 1a10f8379e..0f51a35332 100644 --- a/resources/src/startup.js +++ b/resources/src/startup.js @@ -31,8 +31,8 @@ function isCompatible( ua ) { // Browsers with outdated or limited JavaScript engines get the no-JS experience return !( - // Internet Explorer < 8 - ( ua.indexOf( 'MSIE' ) !== -1 && parseFloat( ua.split( 'MSIE' )[ 1 ] ) < 8 ) || + // Internet Explorer < 9 + ( ua.indexOf( 'MSIE' ) !== -1 && parseFloat( ua.split( 'MSIE' )[ 1 ] ) < 9 ) || // Firefox < 3 ( ua.indexOf( 'Firefox/' ) !== -1 && parseFloat( ua.split( 'Firefox/' )[ 1 ] ) < 3 ) || // Opera < 12 diff --git a/tests/parser/parserTests.txt b/tests/parser/parserTests.txt index a0e0b3a220..d0a3d08b62 100644 --- a/tests/parser/parserTests.txt +++ b/tests/parser/parserTests.txt @@ -14,6 +14,7 @@ # Plus any combination of these: # # cat add category links +# (ignored by Parsoid, since it emits s) # ill add inter-language links # (ignored by Parsoid, since it emits s) # subpage enable subpages (disabled by default) @@ -1335,6 +1336,8 @@ array ( ) +!! html/parsoid +


 !! end
 
 !! test
@@ -3329,14 +3332,18 @@ parsoid=wt2html,wt2wt
   
 !! end
 
+## We used to, but no longer wt2wt this test since the default serializer
+## will normalize all categories to serialize on their own line.
+## This wikitext usage is going to be fairly uncommon in production and
+## selser will take care of preserving formatting in those scenarios.
 !! test
 7b. Indent-pre and category links
 !! options
-parsoid=wt2html,wt2wt
+parsoid=wt2html
 !! wikitext
  [[Category:foo]] a
  [[Category:foo]] {{echo|b}}
-!! html
+!! html/parsoid
 
 a
   b
!! end @@ -7119,6 +7126,17 @@ Piped link with multiple pipe characters in link text

|The|Main|Page|

!! end +!! test +Piped link with no link text +!! wikitext +[[Thomas Bek (bishop of St David's)|]] +!! html/php +

[[Thomas Bek (bishop of St David's)|]] +

+!! html/parsoid +

[[Thomas Bek (bishop of St David's)|]]

+!! end + !! test Broken link !! wikitext @@ -10860,8 +10878,14 @@ Un-closed !! html !! end +## We used to, but no longer wt2wt this test since the default serializer +## will normalize the include directives to serialize on their own line. +## Selser will take care of preserving formatting in scenarios where they +## intermingled with other wikitext. !! test Includes and comments at SOL +!! options +parsoid=wt2html,html2html !! wikitext == hu == @@ -11042,10 +11066,14 @@ parsoid=wt2html,wt2wt !!end +## We used to, but no longer wt2wt this test since the default serializer +## will normalize the include directives to serialize on their own line. +## Selser will take care of preserving formatting in scenarios where they +## intermingled with other wikitext. !!test 2. Table tag in SOL posn. should get reparsed correctly with valid TSR !!options -parsoid=wt2html,wt2wt +parsoid=wt2html !!wikitext a{| {{{b}}} |c @@ -14245,7 +14273,7 @@ cat pst !! wikitext [[Category:MediaWiki User's Guide|]] -!! html +!! html/php [[Category:MediaWiki User's Guide|MediaWiki User's Guide]] !! end @@ -14256,19 +14284,26 @@ cat pst !! wikitext [[Category:Foo (bar)|]] -!! html +!! html/php [[Category:Foo (bar)|Foo]] !! end +## We used to, but no longer wt2wt this test since the default serializer +## will normalize all categories to serialize on their own line. +## This wikitext usage is going to be fairly uncommon in production and +## selser will take care of preserving formatting in those scenarios. !! test Category with link tail !! options cat pst +parsoid=wt2html !! wikitext 123[[Category:Foo]]456 -!! html +!! html/php 123[[Category:Foo]]456 +!! html/parsoid +

123456

!! end !! test @@ -14278,7 +14313,7 @@ cat pst !! wikitext [[Category:{{echo|Foo}}]] -!! html +!! html/php [[Category:{{echo|Foo}}]] !! end @@ -14289,7 +14324,7 @@ cat pst !! wikitext [[Category:Foo|{{echo|Bar}}]] -!! html +!! html/php [[Category:Foo|{{echo|Bar}}]] !! end @@ -14300,12 +14335,18 @@ cat pst !! wikitext [[Category:{{echo|Foo}}|{{echo|Bar}}]] -!! html +!! html/php [[Category:{{echo|Foo}}|{{echo|Bar}}]] !! end +## We used to, but no longer wt2wt this test since the default serializer +## will normalize all categories to serialize on their own line. +## This wikitext usage is going to be fairly uncommon in production and +## selser will take care of preserving formatting in those scenarios. !! test Category / paragraph interactions +!! options +parsoid=wt2html !! wikitext Foo [[Category:Baz]] Bar @@ -14332,7 +14373,7 @@ Bar [[Category:Baz]] {{echo|[[Category:Baz]]}} [[Category:Baz]] -!! html +!! html/php

Foo Bar

Foo Bar @@ -14342,20 +14383,32 @@ Bar

Foo Bar

+!! html/parsoid +

Foo Bar

+

Foo Bar

+

Foo Bar

+

Foo Bar

+

Foo Bar

+ !! end +## We used to, but no longer wt2wt this test since the default serializer +## will normalize all categories to serialize on their own line. +## This wikitext usage is going to be fairly uncommon in production and +## selser will take care of preserving formatting in those scenarios. +## ## The whitespace on the empty line is part of the test. Please do not delete !! test 1. Categories and newlines: All preceding newlines should be suppressed (courtesy bug 87) !! options -parsoid=wt2html,wt2wt +parsoid=wt2html !! wikitext This [[Category:Foo]] and this should be part of same paragraph (not an indent-pre) {{echo|[[Category:Foo]] and so should this!}} -!! html +!! html/php

This and this should be part of same paragraph (not an indent-pre) and so should this!

!! html/parsoid @@ -14453,8 +14506,14 @@ parsoid=wt2html !! end +## We used to, but no longer wt2wt this test since the default serializer +## will normalize all categories to serialize on their own line. +## This wikitext usage is going to be fairly uncommon in production and +## selser will take care of preserving formatting in those scenarios. !! test 6. Categories and newlines: migrateTrailingCategories dom pass should not migrate categories not preceded by newlines +!! options +parsoid=wt2html !! wikitext * a [[Category:Foo]] !! html/parsoid @@ -14505,13 +14564,20 @@ parsoid

!! end -# html2wt localizes the "Category" namespace. -# XXX the element needs an empty data-parsoid attribute, or -# else the html2html test fails because spaces are inserted. +# We used to, but no longer wt2wt this test since the default serializer +# will normalize all categories to serialize on their own line. +# This wikitext usage is going to be fairly uncommon in production and +# selser will take care of preventing whitespace insertion if this +# occurs in an article. +# +# html2html disabled for the same reason (whitespace insertion between +# x and y). +# +# html2wt disabled because it localizes the "Category" namespace. !! test Link prefix/suffixes aren't applied to category links !! options -parsoid=wt2html,wt2wt,html2html +parsoid=wt2html language=is !! wikitext x[[Category:Foo]]y @@ -16152,10 +16218,15 @@ array ( ) +!! html/parsoid +

 !! end
 
+## Don't expect parsoid to rt this form.
 !! test
 Parser hook: empty input using terminated empty elements
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 
 !! html/php
@@ -16165,6 +16236,8 @@ array (
 )
 
 
+!! html/parsoid
+

 !! end
 
 !! test
@@ -16178,6 +16251,8 @@ array (
 )
 
 
+!! html/parsoid
+

 !! end
 
 !! test
@@ -16191,11 +16266,15 @@ array (
 )
 
 
+!! html/parsoid
+

 !! end
 
-
+## Don't expect parsoid to rt this form.
 !! test
 Parser hook: case insensitive
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 input
 !! html/php
@@ -16205,11 +16284,15 @@ array (
 )
 
 
+!! html/parsoid
+

 !! end
 
-
+## Don't expect parsoid to rt this form.
 !! test
 Parser hook: case insensitive, redux
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 input
 !! html/php
@@ -16219,6 +16302,8 @@ array (
 )
 
 
+!! html/parsoid
+

 !! end
 
 !! test
@@ -16234,11 +16319,35 @@ array (
 )
 </tag>
 
+!! html/parsoid
+
</tag>
 !! end
 
 !! test
 Parser hook: basic arguments
 !! wikitext
+
+!! html/php
+
+''
+array (
+  'width' => '200',
+  'height' => '100',
+  'depth' => '50',
+  'square' => '',
+)
+
+ +!! html/parsoid +

+!! end
+
+## Don't expect parsoid to rt this form.
+!! test
+Parser hook: basic arguments, variations
+!! options
+parsoid=wt2html,html2html
+!! wikitext
 
 !! html/php
 
@@ -16251,12 +16360,14 @@ array (
 )
 
+!! html/parsoid +

 !! end
 
 !! test
 Parser hook: argument containing a forward slash (bug 5344)
 !! wikitext
-
+
 !! html/php
 
 ''
@@ -16265,10 +16376,15 @@ array (
 )
 
+!! html/parsoid +

 !! end
 
+## Don't expect parsoid to rt this form.
 !! test
 Parser hook: empty input using terminated empty elements (bug 2374)
+!! options
+parsoid=wt2html,html2html
 !! wikitext
 text
 !! html/php
@@ -16279,6 +16395,8 @@ array (
 )
 text
 
+!! html/parsoid
+
text
 !! end
 
 # 
should be output literally since there is no matching tag that begins it @@ -16311,21 +16429,28 @@ array ( Parser hook: static parser hook not inside a comment !! wikitext hello, world - + + !! html/php -

hello, world +


+hello, world

+!! html/parsoid +

+

hello, world

!! end - !! test Parser hook: static parser hook inside a comment !! wikitext - + !! html/php


+!! html/parsoid + +

!! end # Nested template calls; this case was broken by Parser.php rev 1.506, @@ -19211,17 +19336,25 @@ Category:分類 blah !! endarticle +## We used to, but no longer wt2wt this test since the default serializer +## will normalize all categories to serialize on their own line. +## This wikitext usage is going to be fairly uncommon in production and +## selser will take care of preserving formatting in those scenarios. !! test Don't convert blue categorylinks to another variant (bug 33210) !! options -language=zh cat +cat +language=zh +parsoid=wt2html !! wikitext [[A]][[Category:分类]] -!! html +!! html/php 分类 +!! html/parsoid +

A

+ !! end - !! test Stripping -{}- tags (language variants) !! options @@ -19756,7 +19889,7 @@ Tildes in comments pst !! wikitext -!! html +!! html/php !! end @@ -20078,7 +20211,7 @@ Edit comment with link comment !! wikitext I like the [[Main Page]] a lot -!! html +!! html/php I like the Main Page a lot !!end @@ -20088,7 +20221,7 @@ Edit comment with link and link text comment !! wikitext I like the [[Main Page|best pages]] a lot -!! html +!! html/php I like the best pages a lot !!end @@ -20098,7 +20231,7 @@ Edit comment with link and link text with suffix comment !! wikitext I like the [[Main Page|best page]]s a lot -!! html +!! html/php I like the best pages a lot !!end @@ -20108,7 +20241,7 @@ Edit comment with section link (non-local, eg in history list) comment title=[[Main Page]] !! wikitext /* External links */ removed bogus entries -!! html +!! html/php →‎External links: removed bogus entries !!end @@ -20118,7 +20251,7 @@ Edit comment with section link and text before it (non-local, eg in history list comment title=[[Main Page]] !! wikitext pre-comment text /* External links */ removed bogus entries -!! html +!! html/php pre-comment text →‎External links: removed bogus entries !!end @@ -20128,7 +20261,7 @@ Edit comment with section link (local, eg in diff view) comment local title=[[Main Page]] !! wikitext /* External links */ removed bogus entries -!! html +!! html/php →‎External links: removed bogus entries !!end @@ -20140,7 +20273,7 @@ subpage title=[[Subpage test]] !! wikitext Poked at a [[/subpage]] here... -!! html +!! html/php Poked at a /subpage here... !!end @@ -20152,7 +20285,7 @@ subpage title=[[Subpage test]] !! wikitext Poked at a [[/subpage|neat little page]] here... -!! html +!! html/php Poked at a neat little page here... !!end @@ -20163,7 +20296,7 @@ comment title=[[Subpage test]] !! wikitext Poked at a [[/subpage]] here... -!! html +!! html/php Poked at a /subpage here... !!end @@ -20175,7 +20308,7 @@ local title=[[Main Page]] !! wikitext [[#section]] -!! html +!! html/php #section !! end @@ -20186,24 +20319,28 @@ comment title=[[Main Page]] !! wikitext [[#section]] -!! html +!! html/php #section !! end !! test Anchor starting with underscore +!! options +title=[[Foo]] !! wikitext [[#_ref|One]] -!! html +!! html/php

One

+!! html/parsoid +

One

!! end !! test Id starting with underscore !! wikitext
-!! html +!! html/*
!! end @@ -20215,7 +20352,7 @@ comment title=[[Main Page]] !! wikitext /* __hello__world__ */ -!! html +!! html/php →‎__hello__world__ !! end @@ -20534,17 +20671,20 @@ HTML5 data attributes !! wikitext Baz

Quuz

-!! html +!! html/php

Baz

Quuz

+!! html/parsoid +

Baz

+

Quuz

!! end !! test Strip reserved data attributes !! wikitext -
d
+
d
!! html
d
@@ -21386,14 +21526,12 @@ parsoid=wt2html,wt2wt !!test Ref: 1. ref-location should be replaced with an index span -!!options -parsoid !! wikitext A foo B foo C -!! html +!! html/parsoid

A [1] B [2] C [3]

@@ -21406,13 +21544,11 @@ C foo
B -!! html +!! html/parsoid

A [1] B [1]

    @@ -21422,14 +21558,12 @@ B foo B C -!! html +!! html/parsoid

    A [1] B [1] C [1]

    @@ -21441,12 +21575,10 @@ C foo
    -!! html +!! html/parsoid

    A [1]

    1. ↑ foo
    2. @@ -21455,15 +21587,13 @@ A foo !!test Ref: 5. body should accept generic wikitext -!!options -parsoid !! wikitext A This is a '''[[bolded link]]''' and this is a {{echo|transclusion}} -!! html +!! html/parsoid

      A [1]

        @@ -21474,8 +21604,6 @@ A !!test Ref: 6. indent-pres should not be output in ref-body -!!options -parsoid !! wikitext A foo @@ -21484,7 +21612,7 @@ A -!! html +!! html/parsoid

        A [1]

          @@ -21497,8 +21625,6 @@ A !!test Ref: 7. No p-wrapping in ref-body -!!options -parsoid !! wikitext A foo @@ -21514,7 +21640,7 @@ booz -!! html +!! html/parsoid

          A [1]

            @@ -21534,27 +21660,23 @@ booz !!test Ref: 8. transclusion wikitext has lower precedence -!!options -parsoid !! wikitext A foo {{echo| B C}} -!! html +!! html/parsoid

            A [1] B C}}

              -
            1. ↑ foo {{echo|
            2. +
            3. ↑ foo {{echo|
            !!end !!test Ref: 9. unclosed comments should not leak out of ref-body -!!options -parsoid !! wikitext A foo @@ -21563,13 +21685,11 @@ A foo [[Category:A3]] how goes it == +== [[Category:A3]] how goes it == -== it goes well [[Category:A4]] == +== it goes well [[Category:A4]] == -==howdy [[Category:A5]] == +==howdy [[Category:A5]]== == __TOC__ ok == !! end @@ -25620,7 +25754,7 @@ parsoid={ "modes": ["html2wt"], "suppressErrors": true } # shown to sneak through on occasion. See T101768. # The original wikitext here is: [http://test.com [[one]] two three] !! test -Strip span tags added to mark as misnested +Strip span tags added to mark misnested links !! options parsoid=html2wt !! html/parsoid @@ -25629,10 +25763,112 @@ parsoid=html2wt [http://test.com][[one]] two three !! end +!! test +Use data-parsoid.firstWikitextNode to compute newline constraints for template content +!! options +parsoid=html2wt +!! html/parsoid +a + +
            d +
            +!! wikitext +{{echo|a}} +{|{{echo|c +{{!}}d +}} +|} +!! end + +## This test verifies the presence and computation of this attribute indirectly +## by making an edit and ensuring that the serialization is correct (which it would be +## only if firstWikitextNode is properly set). +!! test +data-parsoid.firstWikitextNode should be computed properly in the presence of fostered content +!! options +parsoid= { + "modes": ["wt2wt"], + "changes": [ + [ "div#x", "remove" ], + [ "div", "before", "
            new
            " ] + ] +} +!! wikitext +
            foo
            +{| +{{echo|
            boo
            +{{!}}b}} +|c +|} +!! wikitext/edited + +
            new
            +{| +{{echo|
            boo
            +{{!}}b}} +|c +|} +!! end + # -------------------------------------------- # Tests spec'ing wikitext serialization norms | # -------------------------------------------- +!! test +1. Categories should always be serialized on their own line +!! options +parsoid=html2wt +!! html/parsoid +foobar +!! wikitext +foo +[[Category:Foo]] +bar +!! end + +!! test +2. Categories that are part of templates should not introduce a line break +!! wikitext +foo {{echo|bar [[Category:baz]]}} bar +!! html/parsoid +

            foo bar bar

            +!! end + +# Careful while editing these next 2 tests. There are \u200f characters +# before and after the tags in the HTML and following some +# of the categories in wikitext +# Do not remove these characters in edits. +# +# As part of the serialization, these bidi characters will get stripped. +!! test +RTL (\u200f) and LTR (\u200e) markers around category tags should be stripped +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

            ‏‏ +‏‏

            +!! wikitext +[[קטגוריה:טקסים]] +[[קטגוריה: שיטות משפט]] +!! end + +!! test +RTL (\u200f) and LTR (\u200e) markers should not be stripped if followed by a text node +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

            ‏‏y

            +!! wikitext +[[קטגוריה:טקסים]] +‏y +!! end + !! test Lists: Add space after bullets !! options @@ -25720,6 +25956,35 @@ parsoid={ !! wikitext/edited !! end +!! test +Headings: Replace
            with a single whitespace char (when scrubWikitext = true) +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": true +} +!! html/parsoid +

            foo
            bar

            +

            foo
            bar
            baz

            +!! wikitext +== foo bar == + +== foo bar baz == +!! end + +!! test +Headings: Replace
            with a single whitespace char (when scrubWikitext = false) +!! options +parsoid={ + "modes": ["html2wt"], + "scrubWikitext": false +} +!! html/parsoid +

            foo
            bar

            +!! wikitext +== foo
            bar == +!! end + !! test 1. WT Quote Tags: suppress newly created empty style tags !! options @@ -26225,10 +26490,61 @@ parsoid=html2wt <nowiki>''foo''</nowiki> !! end +# This is meant to be an interim fix while we go about figuring out +# how to not introduce these trailing s in the first place. +!! test +T115717: Strip trailing s (without affecting valid uses) +!! options +parsoid=html2wt +!! html/parsoid +

            x +y

            +

            +

            +!! wikitext +x +y + +{{echo| +1 = }} + +{{echo| +1 = +}} +!! end + # --------------------------------------------------- # End of tests spec'ing wikitext serialization norms | # --------------------------------------------------- +# T104032 +!! test +Bare inline nodes not wrapped inside p-tags should be treated as p-wrapped +!! options +parsoid=html2wt +!! html/parsoid +a

            b

            +c

            d

            + + + +
            a

            b

            c

            d

            +!! wikitext +a + +b + +'''c''' + +d +{| +|a +b +|'''c''' +d +|} +!! end + # ----------------------------------------------------------------- # End of section for Parsoid-only html2wt tests for serialization # of new content diff --git a/tests/phpunit/data/templates/conds.mustache b/tests/phpunit/data/templates/conds.mustache new file mode 100644 index 0000000000..5ebd2ea3d9 --- /dev/null +++ b/tests/phpunit/data/templates/conds.mustache @@ -0,0 +1 @@ +{{#list}}oh no{{/list}}{{#foo}}none of this should render{{/foo}} \ No newline at end of file diff --git a/tests/phpunit/includes/ExportTest.php b/tests/phpunit/includes/ExportTest.php new file mode 100644 index 0000000000..202603030b --- /dev/null +++ b/tests/phpunit/includes/ExportTest.php @@ -0,0 +1,71 @@ + + */ +class ExportTest extends MediaWikiLangTestCase { + + protected function setUp() { + parent::setUp(); + $this->setMwGlobals( array( + 'wgContLang' => Language::factory( 'en' ), + 'wgLanguageCode' => 'en', + 'wgCapitalLinks' => true, + ) ); + } + + /** + * @covers WikiExporter::pageByTitle + */ + public function testPageByTitle() { + global $wgContLang; + $pageTitle = 'UTPage'; + + $exporter = new WikiExporter( + $this->db, + WikiExporter::FULL + ); + + $title = Title::newFromText( $pageTitle ); + + ob_start(); + $exporter->openStream(); + $exporter->pageByTitle( $title ); + $exporter->closeStream(); + $xmlString = ob_get_clean(); + + // This throws error if invalid xml output + $xmlObject = simplexml_load_string( $xmlString ); + + /** + * Check namespaces match xml + * FIXME: PHP 5.3 support. When we don't support PHP 5.3, + * add ->namespace to object and remove from array + */ + $xmlNamespaces = (array) $xmlObject->siteinfo->namespaces; + $xmlNamespaces = str_replace( ' ', '_', $xmlNamespaces['namespace'] ); + unset ( $xmlNamespaces[ '@attributes' ] ); + foreach ( $xmlNamespaces as &$namespaceObject ) { + if ( is_object( $namespaceObject ) ) { + $namespaceObject = ''; + } + } + + $actualNamespaces = (array) $wgContLang->getNamespaces(); + $actualNamespaces = array_values( $actualNamespaces ); + $this->assertEquals( $actualNamespaces, $xmlNamespaces ); + + // Check xml page title correct + $xmlTitle = (array) $xmlObject->page->title; + $this->assertEquals( $pageTitle, $xmlTitle[0] ); + + // Check xml page text is not empty + $text = (array) $xmlObject->page->revision->text; + $this->assertNotEquals( '', $text[0] ); + } + +} diff --git a/tests/phpunit/includes/ImportLinkCacheIntegrationTest.php b/tests/phpunit/includes/ImportLinkCacheIntegrationTest.php deleted file mode 100644 index 1433b898d0..0000000000 --- a/tests/phpunit/includes/ImportLinkCacheIntegrationTest.php +++ /dev/null @@ -1,112 +0,0 @@ -importStreamSource = ImportStreamSource::newFromFile( $file ); - - if ( !$this->importStreamSource->isGood() ) { - throw new Exception( "Import source for {$file} failed" ); - } - } - - public function testImportForImportSource() { - - $this->doImport( $this->importStreamSource ); - - // Imported title - $loremIpsum = Title::newFromText( 'Lorem ipsum' ); - - $this->assertSame( - $loremIpsum->getArticleID(), - $loremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) - ); - - $categoryLoremIpsum = Title::newFromText( 'Category:Lorem ipsum' ); - - $this->assertSame( - $categoryLoremIpsum->getArticleID(), - $categoryLoremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) - ); - - $page = new WikiPage( $loremIpsum ); - $page->doDeleteArticle( 'import test: delete page' ); - - $page = new WikiPage( $categoryLoremIpsum ); - $page->doDeleteArticle( 'import test: delete page' ); - } - - /** - * @depends testImportForImportSource - */ - public function testReImportForImportSource() { - - $this->doImport( $this->importStreamSource ); - - // ReImported title - $loremIpsum = Title::newFromText( 'Lorem ipsum' ); - - $this->assertSame( - $loremIpsum->getArticleID(), - $loremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) - ); - - $categoryLoremIpsum = Title::newFromText( 'Category:Lorem ipsum' ); - - $this->assertSame( - $categoryLoremIpsum->getArticleID(), - $categoryLoremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) - ); - } - - private function doImport( $importStreamSource ) { - - $importer = new WikiImporter( - $importStreamSource->value, - ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) - ); - $importer->setDebug( true ); - - $reporter = new ImportReporter( - $importer, - false, - '', - false - ); - - $reporter->setContext( new RequestContext() ); - $reporter->open(); - $exception = false; - - try { - $importer->doImport(); - } catch ( Exception $e ) { - $exception = $e; - } - - $result = $reporter->close(); - - $this->assertFalse( - $exception - ); - - $this->assertTrue( - $result->isGood() - ); - } - -} diff --git a/tests/phpunit/includes/ImportTest.php b/tests/phpunit/includes/ImportTest.php deleted file mode 100644 index 9c224309bb..0000000000 --- a/tests/phpunit/includes/ImportTest.php +++ /dev/null @@ -1,162 +0,0 @@ - - */ -class ImportTest extends MediaWikiLangTestCase { - - private function getDataSource( $xml ) { - return new ImportStringSource( $xml ); - } - - /** - * @covers WikiImporter::handlePage - * @dataProvider getRedirectXML - * @param string $xml - * @param string|null $redirectTitle - */ - public function testHandlePageContainsRedirect( $xml, $redirectTitle ) { - $source = $this->getDataSource( $xml ); - - $redirect = null; - $callback = function ( Title $title, ForeignTitle $foreignTitle, $revCount, - $sRevCount, $pageInfo ) use ( &$redirect ) { - if ( array_key_exists( 'redirect', $pageInfo ) ) { - $redirect = $pageInfo['redirect']; - } - }; - - $importer = new WikiImporter( - $source, - ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) - ); - $importer->setPageOutCallback( $callback ); - $importer->doImport(); - - $this->assertEquals( $redirectTitle, $redirect ); - } - - public function getRedirectXML() { - // @codingStandardsIgnoreStart Generic.Files.LineLength - return array( - array( - <<< EOF - - - Test - 0 - 21 - - - 20 - 2014-05-27T10:00:00Z - - Admin - 10 - - Admin moved page [[Test]] to [[Test22]] - wikitext - text/x-wiki - #REDIRECT [[Test22]] - tq456o9x3abm7r9ozi6km8yrbbc56o6 - - - -EOF - , - 'Test22' - ), - array( - <<< EOF - - - Test - 0 - 42 - - 421 - 2014-05-27T11:00:00Z - - Admin - 10 - - Abcd - n7uomjq96szt60fy5w3x7ahf7q8m8rh - wikitext - text/x-wiki - - - -EOF - , - null - ), - ); - // @codingStandardsIgnoreEnd - } - - /** - * @covers WikiImporter::handleSiteInfo - * @dataProvider getSiteInfoXML - * @param string $xml - * @param array|null $namespaces - */ - public function testSiteInfoContainsNamespaces( $xml, $namespaces ) { - $source = $this->getDataSource( $xml ); - - $importNamespaces = null; - $callback = function ( array $siteinfo, $innerImporter ) use ( &$importNamespaces ) { - $importNamespaces = $siteinfo['_namespaces']; - }; - - $importer = new WikiImporter( - $source, - ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) - ); - $importer->setSiteInfoCallback( $callback ); - $importer->doImport(); - - $this->assertEquals( $importNamespaces, $namespaces ); - } - - public function getSiteInfoXML() { - // @codingStandardsIgnoreStart Generic.Files.LineLength - return array( - array( - <<< EOF - - - - Media - Special - - Talk - User - User talk - Portal - Portal talk - - - -EOF - , - array( - '-2' => 'Media', - '-1' => 'Special', - '0' => '', - '1' => 'Talk', - '2' => 'User', - '3' => 'User talk', - '100' => 'Portal', - '101' => 'Portal talk', - ) - ), - ); - // @codingStandardsIgnoreEnd - } - -} diff --git a/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php b/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php index 0b877275ee..552dacb7b9 100644 --- a/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php +++ b/tests/phpunit/includes/changes/RCCacheEntryFactoryTest.php @@ -212,7 +212,7 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase { ), 'child' => array( 'tag' => 'a', - 'content' => 'Talk', + 'content' => 'talk', ) ), $cacheEntry->usertalklink, diff --git a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php index 31e4f5b826..6403905e4e 100644 --- a/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php +++ b/tests/phpunit/includes/db/DatabaseMysqlBaseTest.php @@ -256,4 +256,59 @@ class DatabaseMysqlBaseTest extends MediaWikiTestCase { $this->assertTrue( $pos2->hasReached( $pos1 ) ); $this->assertFalse( $pos1->hasReached( $pos2 ) ); } + + /** + * @dataProvider provideLagAmounts + */ + function testPtHeartbeat( $lag ) { + $db = $this->getMockBuilder( 'DatabaseMysql' ) + ->disableOriginalConstructor() + ->setMethods( array( + 'getLagDetectionMethod', 'getHeartbeatData', 'getMasterServerInfo' ) ) + ->getMock(); + + $db->expects( $this->any() ) + ->method( 'getLagDetectionMethod' ) + ->will( $this->returnValue( 'pt-heartbeat' ) ); + + $db->expects( $this->any() ) + ->method( 'getMasterServerInfo' ) + ->will( $this->returnValue( array( 'serverId' => 172, 'asOf' => time() ) ) ); + + // Fake the current time. + list( $nowSecFrac, $nowSec ) = explode( ' ', microtime() ); + $now = (float)$nowSec + (float)$nowSecFrac; + // Fake the heartbeat time. + // Work arounds for weak DataTime microseconds support. + $ptTime = $now - $lag; + $ptSec = (int)$ptTime; + $ptSecFrac = ( $ptTime - $ptSec ); + $ptDateTime = new DateTime( "@$ptSec" ); + $ptTimeISO = $ptDateTime->format( 'Y-m-d\TH:i:s' ); + $ptTimeISO .= ltrim( number_format( $ptSecFrac, 6 ), '0' ); + + $db->expects( $this->any() ) + ->method( 'getHeartbeatData' ) + ->with( 172 ) + ->will( $this->returnValue( array( $ptTimeISO, $now ) ) ); + + $db->setLBInfo( 'clusterMasterHost', 'db1052' ); + $lagEst = $db->getLag(); + + $this->assertGreaterThan( $lag - .010, $lagEst, "Correct heatbeat lag" ); + $this->assertLessThan( $lag + .010, $lagEst, "Correct heatbeat lag" ); + } + + function provideLagAmounts() { + return array( + array( 0 ), + array( 0.3 ), + array( 6.5 ), + array( 10.1 ), + array( 200.2 ), + array( 400.7 ), + array( 600.22 ), + array( 1000.77 ), + ); + } } diff --git a/tests/phpunit/includes/db/LBFactoryTest.php b/tests/phpunit/includes/db/LBFactoryTest.php index 519d3a0dfb..a64744555a 100644 --- a/tests/phpunit/includes/db/LBFactoryTest.php +++ b/tests/phpunit/includes/db/LBFactoryTest.php @@ -103,9 +103,13 @@ class LBFactoryTest extends MediaWikiTestCase { $dbw = $lb->getConnection( DB_MASTER ); $this->assertTrue( $dbw->getLBInfo( 'master' ), 'master shows as master' ); + $this->assertEquals( + $wgDBserver, $dbw->getLBInfo( 'clusterMasterHost' ), 'cluster master set' ); $dbr = $lb->getConnection( DB_SLAVE ); $this->assertTrue( $dbr->getLBInfo( 'slave' ), 'slave shows as slave' ); + $this->assertEquals( + $wgDBserver, $dbr->getLBInfo( 'clusterMasterHost' ), 'cluster master set' ); $factory->shutdown(); $lb->closeAll(); diff --git a/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php b/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php index 9866ce140d..d2b267a060 100644 --- a/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php +++ b/tests/phpunit/includes/debug/logger/monolog/KafkaHandlerTest.php @@ -167,7 +167,6 @@ class KafkaHandlerTest extends MediaWikiTestCase { } } - public function testBatchHandlesNullFormatterResult() { $produce = $this->getMockBuilder( 'Kafka\Produce' ) ->disableOriginalConstructor() diff --git a/tests/phpunit/includes/exception/HttpErrorTest.php b/tests/phpunit/includes/exception/HttpErrorTest.php index 66fe90c955..0aef146e2a 100644 --- a/tests/phpunit/includes/exception/HttpErrorTest.php +++ b/tests/phpunit/includes/exception/HttpErrorTest.php @@ -60,6 +60,4 @@ class HttpErrorTest extends MediaWikiTestCase { ) ); } - - } diff --git a/tests/phpunit/includes/import/ImportLinkCacheIntegrationTest.php b/tests/phpunit/includes/import/ImportLinkCacheIntegrationTest.php new file mode 100644 index 0000000000..5e3c6268aa --- /dev/null +++ b/tests/phpunit/includes/import/ImportLinkCacheIntegrationTest.php @@ -0,0 +1,112 @@ +importStreamSource = ImportStreamSource::newFromFile( $file ); + + if ( !$this->importStreamSource->isGood() ) { + throw new Exception( "Import source for {$file} failed" ); + } + } + + public function testImportForImportSource() { + + $this->doImport( $this->importStreamSource ); + + // Imported title + $loremIpsum = Title::newFromText( 'Lorem ipsum' ); + + $this->assertSame( + $loremIpsum->getArticleID(), + $loremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + + $categoryLoremIpsum = Title::newFromText( 'Category:Lorem ipsum' ); + + $this->assertSame( + $categoryLoremIpsum->getArticleID(), + $categoryLoremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + + $page = new WikiPage( $loremIpsum ); + $page->doDeleteArticle( 'import test: delete page' ); + + $page = new WikiPage( $categoryLoremIpsum ); + $page->doDeleteArticle( 'import test: delete page' ); + } + + /** + * @depends testImportForImportSource + */ + public function testReImportForImportSource() { + + $this->doImport( $this->importStreamSource ); + + // ReImported title + $loremIpsum = Title::newFromText( 'Lorem ipsum' ); + + $this->assertSame( + $loremIpsum->getArticleID(), + $loremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + + $categoryLoremIpsum = Title::newFromText( 'Category:Lorem ipsum' ); + + $this->assertSame( + $categoryLoremIpsum->getArticleID(), + $categoryLoremIpsum->getArticleID( Title::GAID_FOR_UPDATE ) + ); + } + + private function doImport( $importStreamSource ) { + + $importer = new WikiImporter( + $importStreamSource->value, + ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) + ); + $importer->setDebug( true ); + + $reporter = new ImportReporter( + $importer, + false, + '', + false + ); + + $reporter->setContext( new RequestContext() ); + $reporter->open(); + $exception = false; + + try { + $importer->doImport(); + } catch ( Exception $e ) { + $exception = $e; + } + + $result = $reporter->close(); + + $this->assertFalse( + $exception + ); + + $this->assertTrue( + $result->isGood() + ); + } + +} diff --git a/tests/phpunit/includes/import/ImportTest.php b/tests/phpunit/includes/import/ImportTest.php new file mode 100644 index 0000000000..f4aac235a2 --- /dev/null +++ b/tests/phpunit/includes/import/ImportTest.php @@ -0,0 +1,222 @@ + + */ +class ImportTest extends MediaWikiLangTestCase { + + private function getDataSource( $xml ) { + return new ImportStringSource( $xml ); + } + + /** + * @covers WikiImporter + * @dataProvider getUnknownTagsXML + * @param string $xml + * @param string $text + * @param string $title + */ + public function testUnknownXMLTags( $xml, $text, $title ) { + $source = $this->getDataSource( $xml ); + + $importer = new WikiImporter( + $source, + ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) + ); + + $importer->doImport(); + $title = Title::newFromText( $title ); + $this->assertTrue( $title->exists() ); + + $this->assertEquals( WikiPage::factory( $title )->getContent()->getNativeData(), $text ); + } + + public function getUnknownTagsXML() { + // @codingStandardsIgnoreStart Generic.Files.LineLength + return array( + array( + <<< EOF + + + TestImportPage + Should be ignored + 0 + 14 + + 15 + Should be ignored + 2016-01-03T11:18:43Z + + Should be ignored + Admin + 1 + + wikitext + text/x-wiki + noitazinagro tseb eht si ikiWaideM + phoiac9h4m842xq45sp7s6u21eteeq1 + Should be ignored + + + Should be ignored + +EOF + , + 'noitazinagro tseb eht si ikiWaideM', + 'TestImportPage' + ) + ); + // @codingStandardsIgnoreEnd + } + + /** + * @covers WikiImporter::handlePage + * @dataProvider getRedirectXML + * @param string $xml + * @param string|null $redirectTitle + */ + public function testHandlePageContainsRedirect( $xml, $redirectTitle ) { + $source = $this->getDataSource( $xml ); + + $redirect = null; + $callback = function ( Title $title, ForeignTitle $foreignTitle, $revCount, + $sRevCount, $pageInfo ) use ( &$redirect ) { + if ( array_key_exists( 'redirect', $pageInfo ) ) { + $redirect = $pageInfo['redirect']; + } + }; + + $importer = new WikiImporter( + $source, + ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) + ); + $importer->setPageOutCallback( $callback ); + $importer->doImport(); + + $this->assertEquals( $redirectTitle, $redirect ); + } + + public function getRedirectXML() { + // @codingStandardsIgnoreStart Generic.Files.LineLength + return array( + array( + <<< EOF + + + Test + 0 + 21 + + + 20 + 2014-05-27T10:00:00Z + + Admin + 10 + + Admin moved page [[Test]] to [[Test22]] + wikitext + text/x-wiki + #REDIRECT [[Test22]] + tq456o9x3abm7r9ozi6km8yrbbc56o6 + + + +EOF + , + 'Test22' + ), + array( + <<< EOF + + + Test + 0 + 42 + + 421 + 2014-05-27T11:00:00Z + + Admin + 10 + + Abcd + n7uomjq96szt60fy5w3x7ahf7q8m8rh + wikitext + text/x-wiki + + + +EOF + , + null + ), + ); + // @codingStandardsIgnoreEnd + } + + /** + * @covers WikiImporter::handleSiteInfo + * @dataProvider getSiteInfoXML + * @param string $xml + * @param array|null $namespaces + */ + public function testSiteInfoContainsNamespaces( $xml, $namespaces ) { + $source = $this->getDataSource( $xml ); + + $importNamespaces = null; + $callback = function ( array $siteinfo, $innerImporter ) use ( &$importNamespaces ) { + $importNamespaces = $siteinfo['_namespaces']; + }; + + $importer = new WikiImporter( + $source, + ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) + ); + $importer->setSiteInfoCallback( $callback ); + $importer->doImport(); + + $this->assertEquals( $importNamespaces, $namespaces ); + } + + public function getSiteInfoXML() { + // @codingStandardsIgnoreStart Generic.Files.LineLength + return array( + array( + <<< EOF + + + + Media + Special + + Talk + User + User talk + Portal + Portal talk + + + +EOF + , + array( + '-2' => 'Media', + '-1' => 'Special', + '0' => '', + '1' => 'Talk', + '2' => 'User', + '3' => 'User talk', + '100' => 'Portal', + '101' => 'Portal talk', + ) + ), + ); + // @codingStandardsIgnoreEnd + } + +} diff --git a/tests/phpunit/includes/libs/MemoizedCallableTest.php b/tests/phpunit/includes/libs/MemoizedCallableTest.php index 921bba8466..6edb3d84d6 100644 --- a/tests/phpunit/includes/libs/MemoizedCallableTest.php +++ b/tests/phpunit/includes/libs/MemoizedCallableTest.php @@ -20,7 +20,6 @@ class ArrayBackedMemoizedCallable extends MemoizedCallable { } } - /** * PHP Unit tests for MemoizedCallable class. * @covers MemoizedCallable diff --git a/tests/phpunit/includes/libs/objectcache/BagOStuffTest.php b/tests/phpunit/includes/libs/objectcache/BagOStuffTest.php index 94b74cb651..b9fd6ab81f 100644 --- a/tests/phpunit/includes/libs/objectcache/BagOStuffTest.php +++ b/tests/phpunit/includes/libs/objectcache/BagOStuffTest.php @@ -183,6 +183,18 @@ class BagOStuffTest extends MediaWikiTestCase { $this->assertEquals( $expectedValue, $actualValue, 'Value should be 1 after incrementing' ); } + /** + * @covers BagOStuff::incrWithInit + */ + public function testIncrWithInit() { + $key = wfMemcKey( 'test' ); + $val = $this->cache->incrWithInit( $key, 0, 1, 3 ); + $this->assertEquals( 3, $val, "Correct init value" ); + + $val = $this->cache->incrWithInit( $key, 0, 1, 3 ); + $this->assertEquals( 4, $val, "Correct init value" ); + } + /** * @covers BagOStuff::getMulti */ diff --git a/tests/phpunit/includes/logging/ProtectLogFormatterTest.php b/tests/phpunit/includes/logging/ProtectLogFormatterTest.php index 17decf36fa..8010b77383 100644 --- a/tests/phpunit/includes/logging/ProtectLogFormatterTest.php +++ b/tests/phpunit/includes/logging/ProtectLogFormatterTest.php @@ -160,7 +160,6 @@ class ProtectLogFormatterTest extends LogFormatterTestCase { ); } - /** * @dataProvider provideProtectLogDatabaseRows */ @@ -329,7 +328,6 @@ class ProtectLogFormatterTest extends LogFormatterTestCase { ); } - /** * @dataProvider provideModifyLogDatabaseRows */ @@ -362,7 +360,6 @@ class ProtectLogFormatterTest extends LogFormatterTestCase { ); } - /** * @dataProvider provideUnprotectLogDatabaseRows */ diff --git a/tests/phpunit/includes/media/MediaWikiMediaTestCase.php b/tests/phpunit/includes/media/MediaWikiMediaTestCase.php index 8f28158dcd..cb10be3d27 100644 --- a/tests/phpunit/includes/media/MediaWikiMediaTestCase.php +++ b/tests/phpunit/includes/media/MediaWikiMediaTestCase.php @@ -11,7 +11,6 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase { /** @var string */ protected $filePath; - protected function setUp() { parent::setUp(); diff --git a/tests/phpunit/includes/media/XCFTest.php b/tests/phpunit/includes/media/XCFTest.php index 5b2de151f2..536827ae3a 100644 --- a/tests/phpunit/includes/media/XCFTest.php +++ b/tests/phpunit/includes/media/XCFTest.php @@ -13,7 +13,6 @@ class XCFHandlerTest extends MediaWikiMediaTestCase { $this->handler = new XCFHandler(); } - /** * @param string $filename * @param int $expectedWidth Width diff --git a/tests/phpunit/includes/page/WikiPageTest.php b/tests/phpunit/includes/page/WikiPageTest.php index 0a46f8a18c..002e86f534 100644 --- a/tests/phpunit/includes/page/WikiPageTest.php +++ b/tests/phpunit/includes/page/WikiPageTest.php @@ -1261,22 +1261,6 @@ more stuff ); } - /** - * @dataProvider providePreSaveTransform - * @covers WikiPage::preSaveTransform - */ - public function testPreSaveTransform( $text, $expected ) { - $this->hideDeprecated( 'WikiPage::preSaveTransform' ); - $user = new User(); - $user->setName( "127.0.0.1" ); - - // NOTE: assume Help namespace to contain wikitext - $page = $this->newPage( "Help:WikiPageTest_testPreloadTransform" ); - $text = $page->preSaveTransform( $text, $user ); - - $this->assertEquals( $expected, $text ); - } - /** * @covers WikiPage::factory */ diff --git a/tests/phpunit/includes/registration/ExtensionProcessorTest.php b/tests/phpunit/includes/registration/ExtensionProcessorTest.php index ddf552ef0d..590644fc06 100644 --- a/tests/phpunit/includes/registration/ExtensionProcessorTest.php +++ b/tests/phpunit/includes/registration/ExtensionProcessorTest.php @@ -118,7 +118,8 @@ class ExtensionProcessorTest extends MediaWikiTestCase { '_prefix' => 'eg', 'Bar' => 'somevalue' ), - ) + self::$default; + 'name' => 'FooBar2', + ); $processor->extractInfo( $this->dir, $info, 1 ); $processor->extractInfo( $this->dir, $info2, 1 ); $extracted = $processor->getExtractedInfo(); @@ -166,7 +167,6 @@ class ExtensionProcessorTest extends MediaWikiTestCase { } } - public static function provideExtractMessagesDirs() { $dir = __DIR__ . '/FooBar/'; return array( @@ -194,6 +194,16 @@ class ExtensionProcessorTest extends MediaWikiTestCase { } } + /** + * @covers ExtensionProcessor::extractCredits + */ + public function testExtractCredits() { + $processor = new ExtensionProcessor(); + $processor->extractInfo( $this->dir, self::$default, 1 ); + $this->setExpectedException( 'Exception' ); + $processor->extractInfo( $this->dir, self::$default, 1 ); + } + /** * @covers ExtensionProcessor::extractResourceLoaderModules * @dataProvider provideExtractResourceLoaderModules @@ -400,7 +410,6 @@ class ExtensionProcessorTest extends MediaWikiTestCase { } } - /** * Allow overriding the default value of $this->globals * so we can test merging diff --git a/tests/phpunit/includes/registration/ExtensionRegistryTest.php b/tests/phpunit/includes/registration/ExtensionRegistryTest.php index 201cbfcdf1..543eb5c78d 100644 --- a/tests/phpunit/includes/registration/ExtensionRegistryTest.php +++ b/tests/phpunit/includes/registration/ExtensionRegistryTest.php @@ -25,6 +25,7 @@ class ExtensionRegistryTest extends MediaWikiTestCase { 'defines' => array(), 'credits' => array(), 'attributes' => array(), + 'autoloaderPaths' => array() ); $registry = new ExtensionRegistry(); $class = new ReflectionClass( 'ExtensionRegistry' ); diff --git a/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php b/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php new file mode 100644 index 0000000000..163c52d016 --- /dev/null +++ b/tests/phpunit/includes/site/MediaWikiPageNameNormalizerTest.php @@ -0,0 +1,85 @@ + 3 ), + __METHOD__ + ); + + if ( $res === false || strpos( $res, '"sitename":"Wikidata"' ) === false ) { + $connectivity = false; + } else { + $connectivity = true; + } + } + + if ( !$connectivity ) { + $this->markTestSkipped( 'MediaWikiPageNameNormalizerTest needs internet connectivity.' ); + } + } + + /** + * @dataProvider normalizePageTitleProvider + */ + public function testNormalizePageTitle( $expected, $pageName ) { + $normalizer = new MediaWikiPageNameNormalizer(); + + $this->assertSame( + $expected, + $normalizer->normalizePageName( $pageName, 'https://www.wikidata.org/w/api.php' ) + ); + } + + public function normalizePageTitleProvider() { + // Note: This makes (very conservative) assumptions about pages on Wikidata + // existing or not. + return array( + 'universe (Q1)' => array( + 'Q1', 'Q1' + ), + 'Q404 redirects to Q395' => array( + 'Q395', 'Q404' + ), + 'there is no Q0' => array( + false, 'Q0' + ) + ); + } + +} diff --git a/tests/phpunit/includes/upload/UploadBaseTest.php b/tests/phpunit/includes/upload/UploadBaseTest.php index 9ec1b4667b..90051ee11b 100644 --- a/tests/phpunit/includes/upload/UploadBaseTest.php +++ b/tests/phpunit/includes/upload/UploadBaseTest.php @@ -125,7 +125,6 @@ class UploadBaseTest extends MediaWikiTestCase { ); } - /** * @dataProvider provideCheckSvgScriptCallback */ diff --git a/tests/phpunit/includes/utils/BatchRowUpdateTest.php b/tests/phpunit/includes/utils/BatchRowUpdateTest.php index d224af8ed0..61d9a70a15 100644 --- a/tests/phpunit/includes/utils/BatchRowUpdateTest.php +++ b/tests/phpunit/includes/utils/BatchRowUpdateTest.php @@ -221,7 +221,6 @@ class BatchRowUpdateTest extends MediaWikiTestCase { return call_user_func_array( array( $this, 'onConsecutiveCalls' ), $retvals ); } - protected function genSelectResult( $batchSize, $numRows, $rowGenerator ) { $res = array(); for ( $i = 0; $i < $numRows; $i += $batchSize ) { diff --git a/tests/phpunit/includes/utils/MWCryptHKDFTest.php b/tests/phpunit/includes/utils/MWCryptHKDFTest.php index 2c51af3ce9..5dc049831b 100644 --- a/tests/phpunit/includes/utils/MWCryptHKDFTest.php +++ b/tests/phpunit/includes/utils/MWCryptHKDFTest.php @@ -91,6 +91,4 @@ class MWCryptHKDFTest extends MediaWikiTestCase { ); // @codingStandardsIgnoreEnd } - - } diff --git a/tests/phpunit/maintenance/MaintenanceTest.php b/tests/phpunit/maintenance/MaintenanceTest.php index 5c6a6cde85..245a97af17 100644 --- a/tests/phpunit/maintenance/MaintenanceTest.php +++ b/tests/phpunit/maintenance/MaintenanceTest.php @@ -120,6 +120,16 @@ class MaintenanceFixup extends Maintenance { return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() ); } + public function addOption( $name, $description, $required = false, + $withArg = false, $shortName = false, $multiOccurance = false + ) { + return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() ); + } + + public function getOption( $name, $default = null ) { + return call_user_func_array( array( "parent", __FUNCTION__ ), func_get_args() ); + } + // --- Requirements for getting instance of abstract class public function execute() { @@ -829,4 +839,37 @@ class MaintenanceTest extends MediaWikiTestCase { $this->m->setConfig( $conf ); $this->assertSame( $conf, $this->m->getConfig() ); } + + function testParseArgs() { + $m2 = new MaintenanceFixup( $this ); + // Create an option with an argument allowed to be specified multiple times + $m2->addOption( 'multi', 'This option does stuff', false, true, false, true ); + $m2->loadWithArgv( array( '--multi', 'this1', '--multi', 'this2' ) ); + + $this->assertEquals( array( 'this1', 'this2' ), $m2->getOption( 'multi' ) ); + $this->assertEquals( array( array( 'multi', 'this1' ), array( 'multi', 'this2' ) ), + $m2->orderedOptions ); + + $m2->simulateShutdown(); + + $m2 = new MaintenanceFixup( $this ); + + $m2->addOption( 'multi', 'This option does stuff', false, false, false, true ); + $m2->loadWithArgv( array( '--multi', '--multi' ) ); + + $this->assertEquals( array( 1, 1 ), $m2->getOption( 'multi' ) ); + $this->assertEquals( array( array( 'multi', 1 ), array( 'multi', 1 ) ), $m2->orderedOptions ); + + $m2->simulateShutdown(); + + $m2 = new MaintenanceFixup( $this ); + // Create an option with an argument allowed to be specified multiple times + $m2->addOption( 'multi', 'This option doesn\'t actually support multiple occurrences' ); + $m2->loadWithArgv( array( '--multi=yo' ) ); + + $this->assertEquals( 'yo', $m2->getOption( 'multi' ) ); + $this->assertEquals( array( array( 'multi', 'yo' ) ), $m2->orderedOptions ); + + $m2->simulateShutdown(); + } } diff --git a/tests/phpunit/maintenance/backupTextPassTest.php b/tests/phpunit/maintenance/backupTextPassTest.php index f5dd98b3fb..893e4f90f3 100644 --- a/tests/phpunit/maintenance/backupTextPassTest.php +++ b/tests/phpunit/maintenance/backupTextPassTest.php @@ -1,10 +1,15 @@ setUpStub(); $nameFull = $this->getNewTempFile(); - $dumper = new TextPassDumper( array( "--stub=file:" - . $nameStub, "--output=file:" . $nameFull ) ); + + $dumper = new TextPassDumper( array( "--stub=file:" . $nameStub, + "--output=file:" . $nameFull ) ); + $dumper->prefetch = $prefetchMock; $dumper->reporting = false; $dumper->setDb( $this->db ); @@ -261,7 +268,8 @@ class TextPassDumperDatabaseTest extends DumpTestCase { $this->assertTrue( wfMkdirParents( $nameOutputDir ), "Creating temporary output directory " ); $this->setUpStub( $nameStub, $iterations ); - $dumper = new TextPassDumper( array( "--stub=file:" . $nameStub, + $dumper = new TextPassDumper(); + $dumper->loadWithArgv( array( "--stub=file:" . $nameStub, "--output=" . $checkpointFormat . ":" . $nameOutputDir . "/full", "--maxtime=1" /*This is in minutes. Fixup is below*/, "--buffersize=32768", // The default of 32 iterations fill up 32KB about twice @@ -272,7 +280,7 @@ class TextPassDumperDatabaseTest extends DumpTestCase { // The actual dump and taking time $ts_before = microtime( true ); - $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT ); + $dumper->execute(); $ts_after = microtime( true ); $lastDuration = $ts_after - $ts_before; @@ -634,7 +642,9 @@ class TextPassDumperDatabaselessTest extends MediaWikiLangTestCase { * @dataProvider bufferSizeProvider */ function testBufferSizeSetting( $expected, $size, $msg ) { - $dumper = new TextPassDumperAccessor( array( "--buffersize=" . $size ) ); + $dumper = new TextPassDumperAccessor(); + $dumper->loadWithArgv( array( "--buffersize=" . $size ) ); + $dumper->execute(); $this->assertEquals( $expected, $dumper->getBufferSize(), $msg ); } @@ -674,4 +684,8 @@ class TextPassDumperAccessor extends TextPassDumper { public function getBufferSize() { return $this->bufferSize; } + + function dump( $history, $text = null ) { + return true; + } } diff --git a/tests/phpunit/maintenance/backup_LogTest.php b/tests/phpunit/maintenance/backup_LogTest.php index 7ca45960c5..6629b67dba 100644 --- a/tests/phpunit/maintenance/backup_LogTest.php +++ b/tests/phpunit/maintenance/backup_LogTest.php @@ -2,6 +2,11 @@ /** * Tests for log dumps of BackupDumper * + * Some of these tests use the old constuctor for TextPassDumper + * and the dump() function, while others use the new loadWithArgv( $args ) + * function and execute(). This is to ensure both the old and new methods + * work properly. + * * @group Database * @group Dump * @covers BackupDumper @@ -136,7 +141,8 @@ class BackupDumperLoggerTest extends DumpTestCase { // Preparing the dump $fname = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=file:" . $fname ) ); + + $dumper = new DumpBackup( array( '--output=file:' . $fname ) ); $dumper->startId = $this->logId1; $dumper->endId = $this->logId3 + 1; $dumper->reporting = false; @@ -173,8 +179,10 @@ class BackupDumperLoggerTest extends DumpTestCase { // Preparing the dump $fname = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=gzip:" . $fname, - "--reporting=2" ) ); + + $dumper = new DumpBackup(); + $dumper->loadWithArgv( array( '--logs', '--output=gzip:' . $fname, + '--reporting=2' ) ); $dumper->startId = $this->logId1; $dumper->endId = $this->logId3 + 1; $dumper->setDb( $this->db ); @@ -190,7 +198,7 @@ class BackupDumperLoggerTest extends DumpTestCase { } // Performing the dump - $dumper->dump( WikiExporter::LOGS, WikiExporter::TEXT ); + $dumper->execute(); $this->assertTrue( fclose( $dumper->stderr ), "Closing stderr handle" ); diff --git a/tests/phpunit/maintenance/backup_PageTest.php b/tests/phpunit/maintenance/backup_PageTest.php index 8b6221ba92..5781d1c6d5 100644 --- a/tests/phpunit/maintenance/backup_PageTest.php +++ b/tests/phpunit/maintenance/backup_PageTest.php @@ -6,6 +6,7 @@ * @group Dump * @covers BackupDumper */ + class BackupDumperPageTest extends DumpTestCase { // We'll add several pages, revision and texts. The following variables hold the @@ -98,14 +99,15 @@ class BackupDumperPageTest extends DumpTestCase { function testFullTextPlain() { // Preparing the dump $fname = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=file:" . $fname ) ); + + $dumper = new DumpBackup(); + $dumper->loadWithArgv( array( '--full', '--quiet', '--output', 'file:' . $fname ) ); $dumper->startId = $this->pageId1; $dumper->endId = $this->pageId4 + 1; - $dumper->reporting = false; $dumper->setDb( $this->db ); // Performing the dump - $dumper->dump( WikiExporter::FULL, WikiExporter::TEXT ); + $dumper->execute(); // Checking the dumped data $this->assertDumpStart( $fname ); @@ -153,14 +155,15 @@ class BackupDumperPageTest extends DumpTestCase { function testFullStubPlain() { // Preparing the dump $fname = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=file:" . $fname ) ); + + $dumper = new DumpBackup(); + $dumper->loadWithArgv( array( '--full', '--quiet', '--output', 'file:' . $fname, '--stub' ) ); $dumper->startId = $this->pageId1; $dumper->endId = $this->pageId4 + 1; - $dumper->reporting = false; $dumper->setDb( $this->db ); // Performing the dump - $dumper->dump( WikiExporter::FULL, WikiExporter::STUB ); + $dumper->execute(); // Checking the dumped data $this->assertDumpStart( $fname ); @@ -202,7 +205,8 @@ class BackupDumperPageTest extends DumpTestCase { function testCurrentStubPlain() { // Preparing the dump $fname = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=file:" . $fname ) ); + + $dumper = new DumpBackup( array( '--output', 'file:' . $fname ) ); $dumper->startId = $this->pageId1; $dumper->endId = $this->pageId4 + 1; $dumper->reporting = false; @@ -247,7 +251,8 @@ class BackupDumperPageTest extends DumpTestCase { // Preparing the dump $fname = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=gzip:" . $fname ) ); + + $dumper = new DumpBackup( array( '--output', 'gzip:' . $fname ) ); $dumper->startId = $this->pageId1; $dumper->endId = $this->pageId4 + 1; $dumper->reporting = false; @@ -306,7 +311,7 @@ class BackupDumperPageTest extends DumpTestCase { $fnameMetaCurrent = $this->getNewTempFile(); $fnameArticles = $this->getNewTempFile(); - $dumper = new BackupDumper( array( "--output=gzip:" . $fnameMetaHistory, + $dumper = new DumpBackup( array( "--full", "--stub", "--output=gzip:" . $fnameMetaHistory, "--output=gzip:" . $fnameMetaCurrent, "--filter=latest", "--output=gzip:" . $fnameArticles, "--filter=latest", "--filter=notalk", "--filter=namespace:!NS_USER", diff --git a/tests/phpunit/phpunit.php b/tests/phpunit/phpunit.php index aaa77514f6..09dc931df9 100755 --- a/tests/phpunit/phpunit.php +++ b/tests/phpunit/phpunit.php @@ -242,7 +242,6 @@ if ( version_compare( PHP_VERSION, '5.4.0', '<' ) ) { } ); } - $ok = false; if ( class_exists( 'PHPUnit_TextUI_Command' ) ) { @@ -251,12 +250,19 @@ if ( class_exists( 'PHPUnit_TextUI_Command' ) ) { } else { foreach ( array( stream_resolve_include_path( 'phpunit.phar' ), + stream_resolve_include_path( 'phpunit-old.phar' ), 'PHPUnit/Runner/Version.php', 'PHPUnit/Autoload.php' ) as $includePath ) { - // @codingStandardsIgnoreStart - @include_once $includePath; - // @codingStandardsIgnoreEnd + + if ( $includePath === false ) { + // stream_resolve_include_path can return false + continue; + } + + \MediaWiki\suppressWarnings(); + include_once $includePath; + \MediaWiki\restoreWarnings(); if ( class_exists( 'PHPUnit_TextUI_Command' ) ) { $ok = true; echo "Using PHPUnit from $includePath\n"; diff --git a/tests/phpunit/structure/ApiDocumentationTest.php b/tests/phpunit/structure/ApiDocumentationTest.php deleted file mode 100644 index d2f96dc9cb..0000000000 --- a/tests/phpunit/structure/ApiDocumentationTest.php +++ /dev/null @@ -1,177 +0,0 @@ - false, - 'AllowCategorizedRecentChanges' => false, - ), - array( - 'MiserMode' => true, - 'AllowCategorizedRecentChanges' => true, - ), - ); - - /** - * Initialize/fetch the ApiMain instance for testing - * @return ApiMain - */ - private static function getMain() { - if ( !self::$main ) { - self::$main = new ApiMain( RequestContext::getMain() ); - self::$main->getContext()->setLanguage( 'en' ); - } - return self::$main; - } - - /** - * Test a message - * @param Message $msg - * @param string $what Which message is being checked - */ - private function checkMessage( $msg, $what ) { - $msg = ApiBase::makeMessage( $msg, self::getMain()->getContext() ); - $this->assertInstanceOf( 'Message', $msg, "$what message" ); - $this->assertTrue( $msg->exists(), "$what message {$msg->getKey()} exists" ); - } - - /** - * @dataProvider provideDocumentationExists - * @param string $path Module path - * @param array $globals Globals to set - */ - public function testDocumentationExists( $path, array $globals ) { - $main = self::getMain(); - - // Set configuration variables - $main->getContext()->setConfig( new MultiConfig( array( - new HashConfig( $globals ), - RequestContext::getMain()->getConfig(), - ) ) ); - foreach ( $globals as $k => $v ) { - $this->setMWGlobals( "wg$k", $v ); - } - - // Fetch module. - $module = TestingAccessWrapper::newFromObject( $main->getModuleFromPath( $path ) ); - - // Test messages for flags. - foreach ( $module->getHelpFlags() as $flag ) { - $this->checkMessage( "api-help-flag-$flag", "Flag $flag" ); - } - - // Module description messages. - $this->checkMessage( $module->getDescriptionMessage(), 'Module description' ); - - // Parameters. Lots of messages in here. - $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP ); - $tags = array(); - foreach ( $params as $name => $settings ) { - if ( !is_array( $settings ) ) { - $settings = array(); - } - - // Basic description message - if ( isset( $settings[ApiBase::PARAM_HELP_MSG] ) ) { - $msg = $settings[ApiBase::PARAM_HELP_MSG]; - } else { - $msg = "apihelp-{$path}-param-{$name}"; - } - $this->checkMessage( $msg, "Parameter $name description" ); - - // If param-per-value is in use, each value's message - if ( isset( $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE] ) ) { - $this->assertInternalType( 'array', $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE], - "Parameter $name PARAM_HELP_MSG_PER_VALUE is array" ); - $this->assertInternalType( 'array', $settings[ApiBase::PARAM_TYPE], - "Parameter $name PARAM_TYPE is array for msg-per-value mode" ); - $valueMsgs = $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE]; - foreach ( $settings[ApiBase::PARAM_TYPE] as $value ) { - if ( isset( $valueMsgs[$value] ) ) { - $msg = $valueMsgs[$value]; - } else { - $msg = "apihelp-{$path}-paramvalue-{$name}-{$value}"; - } - $this->checkMessage( $msg, "Parameter $name value $value" ); - } - } - - // Appended messages (e.g. "disabled in miser mode") - if ( isset( $settings[ApiBase::PARAM_HELP_MSG_APPEND] ) ) { - $this->assertInternalType( 'array', $settings[ApiBase::PARAM_HELP_MSG_APPEND], - "Parameter $name PARAM_HELP_MSG_APPEND is array" ); - foreach ( $settings[ApiBase::PARAM_HELP_MSG_APPEND] as $i => $msg ) { - $this->checkMessage( $msg, "Parameter $name HELP_MSG_APPEND #$i" ); - } - } - - // Info tags (e.g. "only usable in mode 1") are typically shared by - // several parameters, so accumulate them and test them later. - if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) { - foreach ( $settings[ApiBase::PARAM_HELP_MSG_INFO] as $i ) { - $tags[array_shift( $i )] = 1; - } - } - } - - // Info tags (e.g. "only usable in mode 1") accumulated above - foreach ( $tags as $tag => $dummy ) { - $this->checkMessage( "apihelp-{$path}-paraminfo-{$tag}", "HELP_MSG_INFO tag $tag" ); - } - - // Messages for examples. - foreach ( $module->getExamplesMessages() as $qs => $msg ) { - $this->checkMessage( $msg, "Example $qs" ); - } - } - - public static function provideDocumentationExists() { - $main = self::getMain(); - $paths = self::getSubModulePaths( $main->getModuleManager() ); - array_unshift( $paths, $main->getModulePath() ); - - $ret = array(); - foreach ( $paths as $path ) { - foreach ( self::$testGlobals as $globals ) { - $g = array(); - foreach ( $globals as $k => $v ) { - $g[] = "$k=" . var_export( $v, 1 ); - } - $k = "Module $path with " . join( ', ', $g ); - $ret[$k] = array( $path, $globals ); - } - } - return $ret; - } - - /** - * Return paths of all submodules in an ApiModuleManager, recursively - * @param ApiModuleManager $manager - * @return string[] - */ - protected static function getSubModulePaths( ApiModuleManager $manager ) { - $paths = array(); - foreach ( $manager->getNames() as $name ) { - $module = $manager->getModule( $name ); - $paths[] = $module->getModulePath(); - $subManager = $module->getModuleManager(); - if ( $subManager ) { - $paths = array_merge( $paths, self::getSubModulePaths( $subManager ) ); - } - } - return $paths; - } -} diff --git a/tests/phpunit/tests/MediaWikiTestCaseTest.php b/tests/phpunit/tests/MediaWikiTestCaseTest.php index 2846fde000..64def9125a 100644 --- a/tests/phpunit/tests/MediaWikiTestCaseTest.php +++ b/tests/phpunit/tests/MediaWikiTestCaseTest.php @@ -6,58 +6,81 @@ */ class MediaWikiTestCaseTest extends MediaWikiTestCase { - const GLOBAL_KEY_EXISTING = 'MediaWikiTestCaseTestGLOBAL-Existing'; const GLOBAL_KEY_NONEXISTING = 'MediaWikiTestCaseTestGLOBAL-NONExisting'; + private static $startGlobals = array( + 'MediaWikiTestCaseTestGLOBAL-ExistingString' => 'foo', + 'MediaWikiTestCaseTestGLOBAL-ExistingStringEmpty' => '', + 'MediaWikiTestCaseTestGLOBAL-ExistingArray' => array( 1, 'foo' => 'bar' ), + 'MediaWikiTestCaseTestGLOBAL-ExistingArrayEmpty' => array(), + ); + public static function setUpBeforeClass() { parent::setUpBeforeClass(); - $GLOBALS[self::GLOBAL_KEY_EXISTING] = 'foo'; + foreach ( self::$startGlobals as $key => $value ) { + $GLOBALS[$key] = $value; + } } public static function tearDownAfterClass() { parent::tearDownAfterClass(); - unset( $GLOBALS[self::GLOBAL_KEY_EXISTING] ); + foreach ( self::$startGlobals as $key => $value ) { + unset( $GLOBALS[$key] ); + } + } + + public function provideExistingKeysAndNewValues() { + $providedArray = array(); + foreach ( array_keys( self::$startGlobals ) as $key ) { + $providedArray[] = array( $key, 'newValue' ); + $providedArray[] = array( $key, array( 'newValue' ) ); + } + return $providedArray; } /** + * @dataProvider provideExistingKeysAndNewValues + * * @covers MediaWikiTestCase::setMwGlobals * @covers MediaWikiTestCase::tearDown */ - public function testSetGlobalsAreRestoredOnTearDown() { - $this->setMwGlobals( self::GLOBAL_KEY_EXISTING, 'bar' ); + public function testSetGlobalsAreRestoredOnTearDown( $globalKey, $newValue ) { + $this->setMwGlobals( $globalKey, $newValue ); $this->assertEquals( - 'bar', - $GLOBALS[self::GLOBAL_KEY_EXISTING], + $newValue, + $GLOBALS[$globalKey], 'Global failed to correctly set' ); $this->tearDown(); $this->assertEquals( - 'foo', - $GLOBALS[self::GLOBAL_KEY_EXISTING], + self::$startGlobals[$globalKey], + $GLOBALS[$globalKey], 'Global failed to be restored on tearDown' ); } /** + * @dataProvider provideExistingKeysAndNewValues + * * @covers MediaWikiTestCase::stashMwGlobals * @covers MediaWikiTestCase::tearDown */ - public function testStashedGlobalsAreRestoredOnTearDown() { - $this->stashMwGlobals( self::GLOBAL_KEY_EXISTING ); - $GLOBALS[self::GLOBAL_KEY_EXISTING] = 'bar'; + public function testStashedGlobalsAreRestoredOnTearDown( $globalKey, $newValue ) { + $this->stashMwGlobals( $globalKey ); + $GLOBALS[$globalKey] = $newValue; $this->assertEquals( - 'bar', - $GLOBALS[self::GLOBAL_KEY_EXISTING], + $newValue, + $GLOBALS[$globalKey], 'Global failed to correctly set' ); $this->tearDown(); $this->assertEquals( - 'foo', - $GLOBALS[self::GLOBAL_KEY_EXISTING], + self::$startGlobals[$globalKey], + $GLOBALS[$globalKey], 'Global failed to be restored on tearDown' ); } diff --git a/tests/qunit/QUnitTestResources.php b/tests/qunit/QUnitTestResources.php index 545718a66e..926e986d6b 100644 --- a/tests/qunit/QUnitTestResources.php +++ b/tests/qunit/QUnitTestResources.php @@ -71,6 +71,7 @@ return array( 'tests/qunit/suites/resources/mediawiki/mediawiki.RegExp.test.js', 'tests/qunit/suites/resources/mediawiki/mediawiki.storage.test.js', 'tests/qunit/suites/resources/mediawiki/mediawiki.template.test.js', + 'tests/qunit/suites/resources/mediawiki/mediawiki.template.mustache.test.js', 'tests/qunit/suites/resources/mediawiki/mediawiki.test.js', 'tests/qunit/suites/resources/mediawiki/mediawiki.html.test.js', 'tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js', @@ -126,6 +127,7 @@ return array( 'mediawiki.toc', 'mediawiki.Uri', 'mediawiki.user', + 'mediawiki.template.mustache', 'mediawiki.template', 'mediawiki.util', 'mediawiki.special.recentchanges', diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js index 4bcb12e6ae..2e63b7a67b 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Title.test.js @@ -332,7 +332,7 @@ } ); - QUnit.test( 'getUrl', 3, function ( assert ) { + QUnit.test( 'getUrl', 4, function ( assert ) { var title; // Config @@ -344,6 +344,9 @@ title = new mw.Title( 'John Doe', 3 ); assert.equal( title.getUrl(), '/wiki/User_talk:John_Doe', 'Escaping in title and namespace for urls' ); + + title = new mw.Title( 'John Cena#And_His_Name_Is', 3 ); + assert.equal( title.getUrl( { meme: true } ), '/wiki/User_talk:John_Cena?meme=true#And_His_Name_Is', 'title with fragment and query parameter' ); } ); QUnit.test( 'newFromImg', 44, function ( assert ) { diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js index 288b527b64..b3c4beeb4e 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.messagePoster.factory.test.js @@ -21,7 +21,7 @@ function () { mw.messagePoster.factory.register( TEST_MODEL, testMessagePosterConstructor ); }, - new RegExp( 'The content model \'' + TEST_MODEL + '\' is already registered.' ), + new RegExp( 'Content model "' + TEST_MODEL + '" is already registered' ), 'Throws exception is same model is registered a second time' ); } ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.template.mustache.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.template.mustache.test.js new file mode 100644 index 0000000000..38ae5e490f --- /dev/null +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.template.mustache.test.js @@ -0,0 +1,32 @@ +( function ( mw ) { + + QUnit.module( 'mediawiki.template.mustache', { + setup: function () { + // Stub register some templates + this.sandbox.stub( mw.templates, 'get' ).returns( { + 'test_greeting.mustache': '
            {{foo}}{{>suffix}}
            ', + 'test_greeting_suffix.mustache': ' goodbye' + } ); + } + } ); + + QUnit.test( 'render', 2, function ( assert ) { + var html, htmlPartial, data, partials, + template = mw.template.get( 'stub', 'test_greeting.mustache' ), + partial = mw.template.get( 'stub', 'test_greeting_suffix.mustache' ); + + data = { + foo: 'Hello' + }; + partials = { + suffix: partial + }; + + html = template.render( data ).html(); + htmlPartial = template.render( data, partials ).html(); + + assert.strictEqual( html, 'Hello', 'Render without partial' ); + assert.strictEqual( htmlPartial, 'Hello goodbye', 'Render with partial' ); + } ); + +}( mediaWiki ) ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js index 0b981065ad..5d72179560 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js @@ -137,9 +137,10 @@ } ); QUnit.test( 'getUrl', 12, function ( assert ) { - // Not part of startUp module - mw.config.set( 'wgArticlePath', '/wiki/$1' ); - mw.config.set( 'wgPageName', 'Foobar' ); + mw.config.set( { + wgArticlePath: '/wiki/$1', + wgPageName: 'Foobar' + } ); var href = mw.util.getUrl( 'Sandbox' ); assert.equal( href, '/wiki/Sandbox', 'simple title' ); @@ -181,8 +182,10 @@ QUnit.test( 'wikiScript', 4, function ( assert ) { mw.config.set( { - wgScript: '/w/i.php', // customized wgScript for bug 39103 - wgLoadScript: '/w/l.php', // customized wgLoadScript for bug 39103 + // customized wgScript for T41103 + wgScript: '/w/i.php', + // customized wgLoadScript for T41103 + wgLoadScript: '/w/l.php', wgScriptPath: '/w' } ); diff --git a/tests/qunit/suites/resources/startup.test.js b/tests/qunit/suites/resources/startup.test.js index d3c4748b69..d3f528c414 100644 --- a/tests/qunit/suites/resources/startup.test.js +++ b/tests/qunit/suites/resources/startup.test.js @@ -21,8 +21,7 @@ 'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 OPR/15.0.1147.153', 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36 OPR/16.0.1196.62', 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 OPR/23.0.1522.75', - // Internet Explorer 8+ - 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)', + // Internet Explorer 9+ 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)', 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko', @@ -47,13 +46,14 @@ 'Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' ], gradeC: [ - // Internet Explorer < 8 + // Internet Explorer < 9 'Mozilla/2.0 (compatible; MSIE 3.03; Windows 3.1)', 'Mozilla/4.0 (compatible; MSIE 4.01; Windows 95)', 'Mozilla/4.0 (compatible; MSIE 5.0; Windows 98;)', 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', 'Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1)', 'Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.0; en-US)', + 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)', // Firefox < 3 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.2) Gecko/20060308 Firefox/1.5.0.2', 'Mozilla/5.0 (X11; U; Linux i686; nl; rv:1.8.1.1) Gecko/20070311 Firefox/2.0.0.1', diff --git a/thumb.php b/thumb.php index fed025874b..04b3e42ac8 100644 --- a/thumb.php +++ b/thumb.php @@ -567,7 +567,6 @@ function wfExtractThumbParams( $file, $params ) { return null; } - /** * Output a thumbnail generation error message *